垃圾佬的正方形
TimeLimit:4000MS MemoryLimit:128MB
64-bit integer IO format:%lld
Problem Description
垃圾佬最近遇到了一个简单题。
给定一系列的棍子,问是否能把它们头尾相连组成正方形(木棍需要用完)。
由于太简单了,垃圾佬懒得去做,于是垃圾佬便把这个问题扔给了你。
Input
第一行一个正整数T,表示测试数据的组数(T<=41)。解下来每行开始于一个正整数N (4<=N<=20), 表示棍子的数目,紧接着的N个正整数字(X1,X2,X3…Xn),表示棍子的长度Xi,(1<=Xi<=10,000)。
Output
对于每组测试数据,如果可能构造成正方形,输出一个“yes”,否则输出“no”。
SampleInput
3
4 1 1 1 1
5 10 20 30 40 50
8 1 7 2 6 4 4 3 5
SampleOutput
yes
no
yes
题意:给你n个木棍问能否用全部的木棍构成一个正方形
思路:深搜+剪枝
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
int a[30];
bool vis[30];
int sum,num,n ;
bool cmp(int a,int b)
{
return a > b;
}
bool dfs(int num,int len,int st)///已经构成边的数目 当前边的长度 添加边的起点
{
if(num == 3)///构成三条边则另一条边已经固定直接返回成功构成
return true;
for(int i = st ;i < n;i ++)
{
if(vis[i])
continue;
vis[i] = true;
if(len+a[i]<sum)///一条边还没构成继续构成改边
{
if(dfs(num,len+a[i],i+1))
return true;
}
else if(len+a[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;
num = 0;
for(int i=0; i<n; i++)
{
scanf("%d",&a[i]);
sum+=a[i];
}
if(sum%4)///如果周长不是4的倍数直接无法构成
{
printf("no\n");
continue;
}
sort(a,a+n,cmp);///升序排序 更长的木棍可选择的条件较少 应该优先处理
sum/=4;
if(a[0]>sum)///如果有最长的木棍比一条边还长也无法构成
{
printf("no\n");
continue;
}
memset(vis,0,sizeof(vis));
if(dfs(0,0,0))
printf("yes\n");
else
printf("no\n");
}
return 0;
}