小记:这题看重的是剪枝,但是都后来发现,其实这应该是一个当初的想法错误,导致的TLE
思路:dfs,一条边一条边的dfs,当能dfs出3条边时,就是yes。当然最开始应该判断%4是否等于0对于总长度。
而dfs的顺序就是从大到小,这点算是剪枝吧,可以少很多工作。
当没组成一条边时,就从大到小搜,一直往小的搜,
而当组成了一条边的时候就要从头开始搜。因为没组成时,可能出现加起来大于一条边的长度的。
我之前wa就出错在没组成一条边,我也是从头开始搜,唉~愚钝!
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <map>
#include <set>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
using namespace std;
#define mst(a,b) memset(a,b,sizeof(a))
#define REP(a,b,c) for(int a = b; a < c; ++a)
#define eps 10e-8
const int MAX_ = 1010;
const int N = 100010;
const int INF = 0x7fffffff;
int C[MAX_];
char str[MAX_][MAX_];
int a[MAX_];
int vis[MAX_];
int n, m, avg;
int dir[4][2] = {{0,-1},{-1,0},{0,1},{1,0}};
int dfs(int sum[], int x)
{
bool flag = 0;
REP(i, 0, 4){
if(sum[i] != avg){flag = 1;break;}
}
if(!flag) return 1;
if(x >= n)return 0;
flag = 0;
int i = x;
//REP(i, x, n){
if(!vis[i]){
REP(j, 0, 4){
if(sum[j] + a[i] <= avg ){
if(sum[j] == 0 && flag)continue;
sum[j] += a[i];
int tmp = dfs(sum, x+1);
if(tmp)return 1;
sum[j] -= a[i];
if(sum[j] == 0)flag = 1;
}
}
}
//}
return 0;
}
int dfs1(int sum, int x,int cur)
{
if(x == 3)return 1;
//printf("%d %d ok\n",sum, x);
REP(i, cur, n){
if(!vis[i]){
if(sum + a[i] == avg){
vis[i] = 1;
int tmp = dfs1(0, x+1, 0);
if(tmp == 1)return 1;
vis[i] = 0;
}
else if(sum + a[i] < avg){
vis[i] = 1;
int tmp = dfs1(sum + a[i], x, i);
if(tmp == 1) return 1;
vis[i] = 0;
}
}
}
return 0;
}
bool cmp(const int a, const int b)
{
return a > b;
}
int main()
{
int T;
scanf("%d", &T);
while(T-- &&scanf("%d", &n)){
int sum = 0;
REP(i, 0, n){
scanf("%d",&a[i]);
sum += a[i];
}
sort(a, a+n, cmp);
if(sum%4 != 0 || n < 4 || a[0] > sum/4){
printf("no\n");
continue;
}
avg = sum/4;
mst(vis, 0);
int ss[4];
mst(ss, 0);
int ans = dfs1(0, 0, 0);//(ss, 0);
if(ans){
printf("yes\n");
}else {
printf("no\n");
}
}
return 0;
}