Square
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 13562 Accepted Submission(s): 4298
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
思路:
题意,给出这么多棍棍,问你能不能拼成正方形。想法肯定是DFS,但是如果是朴素的DFS的话,TLE。。所以这里又需要用剪枝的思想。。。
这里需要剪枝的几个地方是:
1、进行DFS搜索,要标记已经使用了的棍子,一旦不符合要求,就要回溯,并且棍子成为没有使用的状态。
2、当符合要求的棍子数等于5时,说明已经全部构成正方形的边长,结束。
3、每当边长达到要求是,进入下一根棍子DFS搜索。
4、还有最重要的一点:每次遍历一边棍子不要从0开始,从上一次搜索状态的下一根棍子开始遍历,否者会超时。
2、当符合要求的棍子数等于5时,说明已经全部构成正方形的边长,结束。
3、每当边长达到要求是,进入下一根棍子DFS搜索。
4、还有最重要的一点:每次遍历一边棍子不要从0开始,从上一次搜索状态的下一根棍子开始遍历,否者会超时。
5、当flag为true,return的不仅是使flag变为true的那一次dfs,而且还要return 整个dfs,即结束全部的寻找。我就是在这里T了好长时间。。。
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int s[25];
int book[25];
int sum;
int bianchang;
int n;
bool flag=false;
//第一次TLE了,dfs部分需剪枝
void dfs(int num,int nowlen,int dth)
{
if(num>4)
{
flag=true;
return ;
}
if(dth>n)
{
return ;
}
if(nowlen==bianchang)
{
dfs(num+1,0,0);
if(flag==true)return;//剪枝处1
}
for(int i=dth;i<n;i++)
{
if(book[i]==0&&s[i]+nowlen<=bianchang)
{
book[i]=1;
dfs(num,s[i]+nowlen,i+1);
if(flag==true)return ;//剪枝处2
book[i]=0;
}
else if(book[i]==0&&s[i]+nowlen>bianchang) return;
}
}
int main()
{
freopen("in.txt","r",stdin);
int num;
cin>>num;
while(num--)
{
int sum=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&s[i]);
sum+=s[i];
}
if(sum%4!=0)
{
cout<<"no"<<endl;
continue;
}
else bianchang=sum/4;
bool flagg=true;
for(int i=0;i<n;i++)
{
if(s[i]>bianchang)
{
flagg=false;
break;
}
}
if(flagg==false)
{
cout<<"no"<<endl;
continue;
}
memset(book,0,sizeof(book));
sort(s,s+n);
flag=false; //每次记得再将flag初始化
dfs(1,0,0);
if(flag==true)cout<<"yes"<<endl;
else cout<<"no"<<endl;
}
return 0;
}