题意是给你一堆棍子。问你可不可以将他们组成正方形也就是可不可以平分成4份。
用dfs,值得注意的是此题的剪枝问题,直接上代码,看注释吧。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int s[25],sum,flag,n;
bool visit[25];
int cmp(const void *a,const void *b)
{
return *(int *)b-*(int *)a;
}
void dfs(int res,int ans,int x)
{
int i;
if(flag==1) return ;
if(ans==4){flag=1;return ;}
if(res==0) dfs(sum,ans+1,1);
for(i=x;i<=n;i++) //强剪枝,排序后,棍子的长度是递减的,那么当你搜索到不满足条件的棍子时,只需回朔到它的前
//一个搜索位置,而不必回朔到初始位置1。(查找下一个位置时,可用二分加速,此题我就没写那么麻烦了)
{if(!visit[i] && res>=s[i])
{
visit[i]=true; res-=s[i];
dfs(res,ans,i+1);
visit[i]=false; res+=s[i];
}
}
}
int main()
{
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
int i,j,T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
sum=0;
for(i=1;i<=n;i++){
scanf("%d",&s[i]);
sum+=s[i];
}
if(sum%4!=0){ //如果不是4的倍数显然不能分成4份
printf("no\n");
continue;
}
sum/=4;
qsort(&s[1],n,sizeof(s[1]),cmp); //为什么要排序上边已经说明了
//for(i=1;i<=n;i++)
// printf("%d ",s[i]);
if(s[1]>sum){ //如果最大的棍子大于平均值那么也不能满足题意
printf("no\n");
continue;
}
flag=0;
memset(visit,false,sizeof(visit));
dfs(sum,0,1);
if(flag==1)
printf("yes\n");
else printf("no\n");
}
}