描述
给定一组不同长度的棒, 是否有可能加入它们端到端形成一个正方形?
输入
第一行输入包含 N, 测试用例的数量。每个测试用例都以一个整数 4 < = M < = 20 开头, 即棍子的数量。M 整数跟随;每个都给出一根棍子的长度--介于1和1万之间的整数。
输出
对于每种情况, 输出一条包含 "是" 的行, 如果是可能形成一个正方形;否则输出 "否"。
示例输入
3
4 1 1 1 1
5 10 20 30 40 50
8 1 7 2 6 4 4 3 5
示例输出
yes
no
yes
思路:
深搜,如果最长边大于边长或总和不是4的倍数,直接排除情况。具体看代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int m,vis[100001],len[100001],sum,n;//vis为标记数组,len为输入的长度,sum为这组len的总和
bool dfs(int di,int shengyu,int beginx)//di表示第几条边......有点随意 shengyu表示当前这条边还剩多少,从beginx后面继续找
{
if(di==4) return true;//如果成功,返回1
else for(int i=beginx;i<m;i++)//从beginx开始搜
{
if(vis[i]==0)//如果未被标记
{
vis[i]=1;//标记
if(shengyu==len[i])//如果剩下的正好配对
{
if(dfs(di+1,sum/4,0)) return true;//搜索下一条边
}
else if(len[i]<shengyu)//如果不够剩余
{
if(dfs(di,shengyu-len[i],i+1)) return true;//继续搜索
}
vis[i]=0;//回溯
}
}
return false;//返回0
}
int main()
{
cin>>n;
while(n--)//多组数据输入
{
int maxl=0;
sum=0;//每次置0
scanf("%d",&m);//输入
for(int j=0;j<m;j++)
{
scanf("%d",&len[j]);
maxl=max(len[j],maxl);//求最大值
sum+=len[j];//求出总和
}
if(sum%4!=0||maxl>sum/4)//判断能否构成
{
cout<<"no"<<endl;//输出no
continue;
}
memset(vis,0,sizeof(vis));//标记置0
if(dfs(1,sum/4,0)) printf("yes\n");//搜索&输出
else printf("no\n");
}
}