题意:给一组木棍,问能否把它们全部用上,首尾相接构成一个正方形
很明显的dfs,需要剪枝,不过挺好想的,但是每次搜的位置不好想,因为对于每一条边,如果前面已经搜过的木棍用不上,那么它就永远用不上,就直接往后搜
对于标记,把所有搜过的木棍都标记,然后没有用到的取消标记,用到的进入下一次的搜索
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<set>
#include<queue>
#include<map>
using namespace std;
int len[25],vis[25];
int n,sum,ave;
bool dfs(int cnt,int left,int st)
//cnt代表第几边,left代表剩下的长度,st代表从哪里开始
{
int i,j;
if(cnt==4)return 1;
for(i=st;i<n;i++)
{
if(!vis[i])
{
vis[i]=1;//全部标记为搜过
if(left==len[i])
{
if(dfs(cnt+1,ave,0))return 1;//下一边
}
else if(left>len[i])
{
if(dfs(cnt,left-len[i],i+1))return 1;//从i+1的为位置开始搜
}
vis[i]=0;//如果没有用到,取消标记
}
}
return 0;
}
int main()
{
int T,i,j,MAX;
scanf("%d",&T);
while(T--)
{
sum=0;
MAX=0;
memset(vis,0,sizeof(vis));
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d",&len[i]);
sum+=len[i];
if(MAX<len[i])
MAX=len[i];
}
ave=sum/4;
if(sum%4||ave<MAX)
{
printf("no\n");
continue;
}//sum能除四,最大的木棍不超过边长
else
{
if(dfs(1,ave,0))printf("yes\n");
else printf("no\n");
}
}
return 0;
}