题目大意:
给定一些木棒,问是否可以用这些木棒头尾相连成一个正方形。
解题思路:
DFS+剪枝
本题可以理解为把这些木棒拼接成四根长度相同的大木棒,所有木棒的总长度sum为正方形周长,sum/4是变长
不难看出,小棒的长度越长,灵活性越差,由此,我们要对这些木棒进行降序排序,从最长的棒子DFS
剪枝:
1、要组合成正方形,必须满足sum%4==0;
2、所有小棒中最长的一根Max_length<=sum/4;
3、当满足1,2时,只需能组合成三条边,就能确定这些棒子能拼成正方形;
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int n,sticks[30];
int vis[30];
int sum,num;
bool cmp(int n,int m){
return n>m;
}
bool dfs(int num,int len,int st){ //num:已组合的正方形的边数;len:当前正在组合的边的已组合长度;
//st:sticks[]的搜索起点
if(num==3){ //剪枝3,当满足剪枝1和剪枝2的要求时,只需组合三条边,剩下的木棒必能组合成
return true; //另一条边;
}
for(int i=st;i<n;i++){
if(vis[i]){
continue;
}
vis[i]=true;
if(len+sticks[i]<sum){
if(dfs(num,len+sticks[i],i+1)) //继续构建当前边
return true;
}
else if(len+sticks[i]==sum){
if(dfs(num+1,0,0)){ //构建新的边
return true;
}
}
vis[i]=false;
}
return false;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
sum=0;
for(int i=0;i<n;i++){
scanf("%d",&sticks[i]);
sum+=sticks[i];
}
if(sum%4){ //剪枝1
printf("no\n");
continue;
}
sort(sticks,sticks+n,cmp);
sum/=4;
num=0;
if(sticks[0]>sum){ //剪枝2
printf("no\n");
continue;
}
memset(vis,0,sizeof(vis));
if(dfs(0,0,0)){
printf("yes\n");
}
else{
printf("no\n");
}
}
return 0;
}
参考博客:http://blog.youkuaiyun.com/lyy289065406/article/details/6647955