PS: 经典的DFS+剪枝。当已经完成一条边的组合后,要从头开始搜索,如果还没组合成一条边则从当前下标位置继续搜索,如果访问过则找下一个满足条件的数字。
剪枝技术可以参考POJ1011 stick。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 24;
bool cmp(int a, int b) {
return a>b ? true : false;
}
int n;
int d[maxn];
bool used[maxn];
//Accepted 1518 578MS 240K 1207 B C++ Achiberx
bool dfs(int idx, int add, int cnt, int len) {
if(cnt==3) return true;
if(add==len) {
if(dfs(1, 0, cnt+1, len)==true) return true;
} else {
for(int i = idx; i <= n; i++) { // for(int i = 1; i <= n; i++) TLE.
if(used[i]) continue;
if(add+d[i]>len) continue; // cut branch.
used[i]=true;
if(dfs(i+1, add+d[i], cnt, len)==true) return true;
used[i]=false;
}
}
return false;
}
int main()
{
int T;
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
int sum = 0;
for(int i = 1; i <= n; i++) {
scanf("%d", &d[i]);
sum += d[i];
}
sort(d+1, d+n+1, cmp);
if(sum%4 || (sum%4==0 && d[1]>sum/4)) {
printf("no\n");
continue;
}
memset(used, false, sizeof(used));
if(dfs(1,0,0,sum/4)==true) {
printf("yes\n");
} else printf("no\n");
}
return 0;
}