题目大意 给出n根木棍,问是否可以首尾相连组成一个正方形。
算法 dfs+剪枝,合理巧妙的剪枝是避免TLE的关键;
1.特判,当木棍总长度不正好是4的倍数时,pass;
2.最长的木棍比边长小时,pass;
3.对木棍长排序,每次都从当前最大到小枚举,在同一条边中,之前放不下的木棍现在也一定放不下;
4.已经确定有解时,跳过剩下的过程;
5.三条边都可以,第四条一定可以。
代码实现
<span style="font-size:18px;">#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
bool f,vis[22];
int n,a[22],sum;
void dfs(int step,int ans,int st) //当前处理第几条边;总长度;当前最长木棍长;
{
if (f) return;
if (step>3)
{
f=1;
return;
}
for (int i=st;i;i--)
{
if(!vis[i]&&ans+a[i]<=sum)
{
ans+=a[i];
vis[i]=true;
if (ans==sum) dfs(step+1,0,n);
else dfs(step,ans,i-1); //更新当前最大木棍长;
if (f) return;
ans-=a[i];
vis[i]=0;
}
}
}
int main()
{
int t;
cin>>t;
while (t)
{
t--;
sum=0;
cin>>n;
memset(a,0,sizeof(a));
for (int i=1;i<=n;i++)
{
cin>>a[i];
sum+=a[i];
}
if (sum%4!=0)
{
cout<<"no"<<endl;
continue;
}
sum/=4;
memset(vis,false,sizeof(vis));
sort(a+1,a+n+1);
if (a[n]>sum)
{
cout<<"no"<<endl;
continue;
}
f=0;
dfs(1,0,n);
if (f) cout<<"yes"<<endl;
else cout<<"no"<<endl;
}
return 0;
}
</span>