```cpp
#include<bits/stdc++.h>//万能头不解释
using namespace std;
int t,n,an,ans=4;//分别为:数据数,木棒数,每边应有长度,剩余未拼成的边数
bool booka[20];//标记木棒是否使用过
bool flag;//是否拼成
int a[20];//木棒长度
void dfs(int sum)
{
if(ans==0)//若应拼边数为零,则已拼好
{
flag=true;
return;//打上已完成的标记
}
if(!flag)//若没有完成
{
for(int i=0;i<n;i++)
{
if(sum+a[i]==an&&!booka[i])/*如果此数没有用到且当前长度加上已拼好的长度等于边长,即又拼好了一边,则应拼边数自减,打上标记,已拼好的长度回到0,进行下一边*/
{
ans--;
booka[i]=true;
dfs(0);
if(flag) return;/*剪枝,若已拼好,则不进行之后的计算(后同)*/
ans++; //回溯
booka[i]=false;
}
if(sum+a[i]>an) return;/*排序的作用:若现在边长+此边长大于应有边长,则这个不可能,后续数均大于等于此数,所以后面也不可能,直接返回上层*/
else if(!booka[i])//非特殊条件,进行下一次操作
{
booka[i]=true;
dfs(sum+a[i]);
if(flag) return;
booka[i]=false;
}
}
}
else return;
}
int main()
{
cin>>t;
while(t--)
{
cin>>n;
int maxn=0;//记录木棒总长
for(int i=0;i<n;i++)
{
cin>>a[i];
booka[i]=false;//边读入边赋值,相当于循环外加memset
maxn+=a[i];
}
sort(a+0,a+n-1);//先排序,dfs剪枝用
if(maxn%4!=0)
{
cout<<"no"<<endl;
continue;
}/*因为题目要求全部用到,所以若总长不是4的倍数,则不可能全用完且拼成*/
an=maxn/4;//每边应有长度
for(int i=0;i<n;i++) if(a[i]==an) ans--;/*若有某一边长等于应有边长,则需要拼的边数减一,即已经拼好一根*/
if(ans==0)//若应拼的边数为零,则已经拼好,输出
{
cout<<"yes"<<endl;
continue;
}
dfs(0);//dfs,参数是当前拼的边的长度
if(flag) cout<<"yes"<<endl;//输出
else cout<<"no"<<endl;
ans=4;//未拼好边数恢复4
flag=false;//恢复标记为未拼成
}
}
by AlexSong @ 2023-09-02 12:44:52
谢谢
by WT985_AK_IOI @ 2023-09-03 09:35:29