题目点我
简单的深度优先搜索,由于搜索树同一层中同样的数只要试一次,有一点判断重复的小技巧。
没加剪枝也16ms水过,等打球回来看看有哪能优化的。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define maxn 15
int t, n, nTotalSum;
int nNum[maxn], nPath[maxn];
bool bUsed[maxn];
bool dfs(int nSum, int nCurIdx, int nCnt){
if((nSum == 0) && (nCurIdx < n)){
for(int i = 0; i < nCnt; i++){
printf("%d", nNum[nPath[i]]);
if(i == nCnt - 1)
printf("\n", nPath[i]);
else
printf("+", nPath[i]);
}
return true;
}
bool bSolvedOnce = false, bSolved = false;
for(int i = nCurIdx; i < n; i++){
if((bUsed[i] == false) && (nNum[i] <= nSum)){
//判断重复的方法:和前一个数相等时,前一个数如果标记已使用,说明这个数是在(搜索树的)下一层用,不能跳过
// 如果前一个数标记未使用,说明这个数要取代前一个数在同一层使用,需要跳过
if((nNum[i - 1] == nNum[i]) && (bUsed[i - 1] == false) && (i > 0))
continue;
bUsed[i] = true;
nPath[nCnt] = i;
bSolvedOnce = dfs(nSum - nNum[i], i, nCnt + 1);
bUsed[i] = false;
nPath[nCnt] = -1;
}
bSolved = bSolved || bSolvedOnce;
}
return bSolved;
}
int main(){
while(scanf("%d %d", &t, &n) != EOF){
if((t == 0) && (n == 0))
break;
nTotalSum = 0;
for(int i = 0; i < n; i++){
scanf("%d", &nNum[i]);
nTotalSum += nNum[i];
}
memset(bUsed, false, sizeof(bUsed));
memset(nPath, -1, sizeof(nPath));
printf("Sums of %d:\n", t);
bool nSolved = dfs(t, 0, 0);
if(nSolved == false)
printf("NONE\n");
}
return 0;
}