觉得这个题目还有点意思 就花了点时间做了下
这个题目的规模实在是大 别看就只有126个数据 但是问题搜索范围是2的126次方
没估算过 所有情况都一一遍历的话 需要多长时间 应该是需要很久的
这类运算量大的题目 保留中间计算结果 尽量减少重复计算的次数 应该是一个好的优化算法的思路
我在2楼的递归算法的基础上 做了3点改进 
仍然是从大到小排序 从大数开始选择 但是每次递归改为求解剩余需要组合的值 比如sum=9 已经选择了 6 那么从6之后 求解能合成3的方法 
具体改进的地方:
1. 向后搜索时 不是一一搜索 而是跳过比sum值大的值 因为他肯定不是有效组合 只要加上他就超了 就不用试了
2. 判断如果这之后所有的值都加起来的和比sum值要小 那么就终止本轮搜索 向前回溯 因为即使加上所有值 都组不成有效解
3. 保留中间过程的计算结果 比如在求解过程中 发现 在搜索sum=9时 从位置5往后没有可行解
   那么下次再要搜索9时而且起始位置在5或之后 就根据这个信息直接结束递归并向前回溯
其实 起到真正效果的是 第3点 前两点的优化效果不是很明显
但是 不幸的是 经过求解发现 楼主给的2894是找不到有效组合的 有可能是真的没有可行解 不过结论仅供参考
下面是代码 发现bug 欢迎指出 不懂算法 纯属个人瞎编
编译器 mingw5,C编译器不支持内置bool 请修改代码中相应符号定义

程序代码:
#include <stdio.h>
#include <stdlib.h>
#define Compiler_CPP    //编译器类型 判断是否支持内置bool类型
#define Display_ON        //控制台显示开关 是否打开中间过程显示
#define IN_FILE "in.txt"
#define OUT_FILE "out.txt"
#define DATA_SIZE 9*14
#define SUM 2894
#ifdef Compiler_C
typedef enum{false, true} bool;
#endif
typedef enum{open, append, close} option;
typedef struct
{
    bool flag;
    int pos;
}feas;        //可解标志 判断对于指定值在某个位置之后是否存在可行解 
 
int g_dat[DATA_SIZE];
int g_cum[DATA_SIZE];
int g_res[DATA_SIZE];
feas g_midres[SUM+1];
void input(void);
void init(void);
void output(option outmode, int num);
bool solve(int sum, int datpos, int respos);
int main()
{
    input();
    init();
    output(open, 0);
    if(solve(SUM, 0, 0))
        printf("\rAll cases are tried and at most one solution is found.\n");
    else
        printf("\rAll cases are tried and none solution is found.\n");
    output(close, 0);
    return 0;
}
void input(void)
{
    int i;
    FILE *fp;
     
    if((fp=fopen(IN_FILE, "r")) == NULL){
        printf("Open file %s failed!\n", IN_FILE);
        exit(1);
    }
    for(i = 0; i < DATA_SIZE; i++)
        fscanf(fp, "%d", g_dat+i);
    
    fclose(fp);
}
static int cmp_lt(const void *p1, const void *p2)
{
    return (*(int*)p2 - *(int*)p1);
}
void init(void)
{
    int i;
    
    qsort(g_dat, DATA_SIZE, sizeof(int), cmp_lt);
    
    g_cum[DATA_SIZE-1] = g_dat[DATA_SIZE-1];
    for(i = DATA_SIZE-2; i >= 0; i--)
        g_cum[i] = g_cum[i+1] + g_dat[i]; 
        
    for(i = 0; i < SUM+1; i++)
        g_midres[i].flag = true;    
} 
void output(option outmode, int num)
{
    int i;
    static FILE *fp;
    static int cnt = 0;
    
    switch(outmode){
        case open:
            goto pro_open;
        case append:
            goto pro_append;
        case close:
            goto pro_close;
        default:
            return;
    }
pro_open:
    if((fp=fopen(OUT_FILE, "w"))==NULL){
        printf("Open file %s failed!\n", OUT_FILE);
        exit(1);
    }
    fprintf(fp, "[ORDER]\t[Feasible Solutions(sum is %d)]\n", SUM);
    return;
pro_append:
    fprintf(fp, " %05d\t ", ++cnt);    
    for(i = 0; i < num; i++)
        fprintf(fp, "%4d\t", g_res[i]);        
    fprintf(fp, "\n");
    
    #ifdef Display_ON
    printf("\rORDER %d: ", cnt);
    for(i = 0; i < num; i++)
        printf("%4d ", g_res[i]);        
    printf("\n");
    for(i = 0; i < num; i++)
        printf("%4d ", g_res[i]);
    #endif
    
    return;
    
pro_close:
    fclose(fp);
    return;
}
static int next(int pos, int val)
{
    while(pos<DATA_SIZE && g_dat[pos]>val)
        pos++;
    
    return pos;
}
bool solve(int sum, int datpos, int respos)
{
    bool is_solved;
    int nextpos;
    
    if(sum == 0){
        if(respos == 0)
            return false;
            
        output(append, respos);
        return true;
    }    
    else if(sum <= g_cum[datpos]){
        is_solved = false;
        nextpos = next(datpos, sum);
        while(nextpos < DATA_SIZE){
            #ifdef Display_ON
            printf("%4d ", g_dat[nextpos]);
            #endif
            
            g_res[respos] = g_dat[nextpos];
            if(g_midres[sum-g_dat[nextpos]].flag ||
               g_midres[sum-g_dat[nextpos]].pos > nextpos+1){
                   if(solve(sum-g_dat[nextpos], nextpos+1, respos+1)){
                       is_solved = true;
                   }
                   else{
                       g_midres[sum-g_dat[nextpos]].flag = false;
                       g_midres[sum-g_dat[nextpos]].pos = nextpos+1;
                   }
               }
               
               #ifdef Display_ON
            printf("\b\b\b\b\b");
            #endif
            
            while(nextpos<DATA_SIZE && g_dat[nextpos]==g_res[respos])
                nextpos = next(nextpos+1, sum);
        }
        return is_solved;
    }
    else return false; 
}