Square
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 5742 Accepted Submission(s): 1823
3 4 1 1 1 1 5 10 20 30 40 50 8 1 7 2 6 4 4 3 5
yes no yes
#include <iostream>
#include <algorithm>
using namespace std;
int n,s,k,a[22],visit[22]={0}; //a数组用来记录那一组数据,visit数组用来记录当前组的数据是否可用
void DFS(int sum,int x,int d) //sum是当前计算的和,等于正方形边长的话就配好了一条边了,x是记录当前配好了多少条边,d是上一次匹配到了哪里,是剪枝的关键
{
if(k||x==3) //当配上了三边的时候就说明能构成正方形了,如果已经能配成正方形就直接返回了
{
k=1;return; //k=1标记已经能够成正方形了
}
int i;
for(i=d;i<n;i++) //从上次断点开始匹配
{
if(k)return; //已经构成正方形就直接返回
if(!visit[i]) //询问这第i组数据是否可用
if(sum+a[i]==s) //如果正好配成边
{
visit[i]=1;
DFS(0,x+1,0); //初始化s和d并已经配成的边+1
visit[i]=0;
}
else if(sum+a[i]<s) //如果比边小
{
visit[i]=1;
DFS(sum+a[i],x,i+1); //传送断点和此时的值
visit[i]=0;
}
}
}
bool cmp(int a,int b)
{
return a<b;
}
int main(void)
{
int m,i;
cin>>m;
while(m--&&cin>>n)
{
for(i=s=0;i<n;i++)
cin>>a[i],s+=a[i]; //统计正方形周长
sort(a,a+n,cmp); //从小到大排序
if(s%4==0) //判断周长是否是正方形的形式
{
s/=4; //s变成记录正方形的边长
k=0; //初始化k
DFS(0,0,0); //和为0,已配成的边数量为0,断点是起点
if(k)cout<<"yes"<<endl;
else cout<<"no"<<endl;
}
else cout<<"no"<<endl;
}
return 0;
}