Square
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 5710 Accepted Submission(s): 1812
Problem 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
Source
Recommend
LL
解题思路:本题为深度优先搜索典型题目,重点在于看懂题目,化整为零逐个击破。我开始以为题目的意思是说,在给出的棍子里面随便拿一些出来拼接,只要能拼成正方形即可。郁闷了很久,事实证明,我理解错了。题目的意思是,所有的棍子都得用上,问能不能拼出正方形。这样,就简单多了,就只要四次拼出总长度的4分之一久可以了,还可以根据总长能否整分和最长的棍子与平均值长度的关系直接剪枝。
解题思路:本题为深度优先搜索典型题目,重点在于看懂题目,化整为零逐个击破。我开始以为题目的意思是说,在给出的棍子里面随便拿一些出来拼接,只要能拼成正方形即可。郁闷了很久,事实证明,我理解错了。题目的意思是,所有的棍子都得用上,问能不能拼出正方形。这样,就简单多了,就只要四次拼出总长度的4分之一久可以了,还可以根据总长能否整分和最长的棍子与平均值长度的关系直接剪枝。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,a[20],flag[20];
int max_len,avr;
int f;
void dfs(int start,int count,int len)
{
if(len>avr||f)
return ;
if(len==avr) //一条边拼接完成
{
count++;
if(count==4) //四条边拼接完成
{
f=1;
return ;
}
len=0;
start=0;
}
if(f)
return ;
for(int i=start;i<n;i++)
{
if(!flag[i])
{
flag[i]=1;
dfs(i,count,len+a[i]);
flag[i]=0;
}
}
}
int main()
{
int t;
int i;
scanf("%d",&t);
while(t--)
{
f=0;
max_len=0;
int sum=0;
memset(flag,0,sizeof(flag));
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
sum+=a[i];
max_len=max(a[i],max_len);
}
if(sum%4!=0||max_len>sum/4); // 总数不能整分或最大值大于平均值,皆不能拼成正方形
else
{
avr=sum/4;
dfs(0,0,0);
}
if(f)
printf("yes\n");
else
printf("no\n");
}
return 0;
}