Description
Given a set of sticks of various lengths, is it possible to join them end-to-end to form a square?
Input
The first line of input contains N, the number of test cases. Each test case begins with an integer 4 <= M <= 20, the number of sticks. M integers follow; each gives the length of a stick - an integer between 1 and 10,000.
Output
For each case, output a line containing "yes" if is is possible to form a square; otherwise output "no".
Sample Input
3 4 1 1 1 1 5 10 20 30 40 50 8 1 7 2 6 4 4 3 5
Sample Output
yes no yes
题目大意:
给出一组数据,问能否组成正方形,数据不能拆分。
本题采用深度搜索,看能否找到四组数据,其和相等。具体思路请详看代码及注释。
代码如下:
#include<stdio.h>
#include<string.h>
/*M:棒的数目;sum:正方形每边的应有长度;
flag:标记能否搜索出三边;一维数组(a):储存每个棒的长度;
一维数组(vis)标记每一个棒是否用过。*/
int M,sum,L,flag,a[30],vis[30];
/*深度搜索(DFS),搜索每一边,当搜索到三边时,便可构成正方形;
bian:代表当前搜索第几条边;L:代表当前边的长度;
k: */
void dfs(int bian,int L,int k)
{
int i;
//所以棒长度的和能被4整除时,只有搜索出三边相等,
//则第四条边一定与前三条边相等,即可以构成正方形
if(bian==4)
{
flag=1;
return ;
}
//当搜索的边达到应有的长度时,搜索下一条边
if(L==sum)
{
dfs(bian+1,0,0);
if(flag)
return ;
}
//遍历所有的棒,去除已经用过(即标记的),去组成新的边
for(i=k;i<M;i++)
{
if(!vis[i]&&L+a[i]<=sum)
{
vis[i]=1;//标记已经用过的棒
dfs(bian,a[i]+L,i+1);//
if(flag)
return;
vis[i]=0;//
}
}
}
int main()
{
int i,N;
scanf("%d",&N);
while(N--)
{
sum=0;
scanf("%d",&M);
for(i=0;i<M;i++)
{
scanf("%d",&a[i]);
sum+=a[i];
}
if(sum%4!=0)
{
printf("no\n");
continue;
}
sum=sum/4;
for(i=0;i<M;i++)
{
if(a[i]>sum)
break;
}
if(i!=M)
{
printf("no\n");
continue;
}
//初始化标记数组(vis),值为零表示未标记
memset(vis,0,sizeof(vis));
flag=0;
dfs(1,0,0);
if(flag)
printf("yes\n");
else
printf("no\n");
}
return 0;
}