#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
using namespace std;
int stick[205];
bool visit[205];
int n, m, sum;
bool bfs(int fran, int side, int sl)//fran表示可以选择的木棍的范围,木根默认排序,sl表示当前这条边已经组成的长度
{
if (side == 3)
return true;
else
{
for (int i = fran; i >= 0; i--)
{
if (!visit[i])
{
visit[i] = true;//避免递归进行访问时重复访问
if (stick[i] + sl < sum)
{
if (bfs(i - 1, side, stick[i] + sl))
return true;
}
if (stick[i] + sl == sum)
{
if (bfs(m - 1, side + 1, 0))//当前边长清零
return true;
}
visit[i] = false;
}
}
}
return false;
}
int main()
{
int n;
cin >> n;
while (n--)
{
cin >> m;
memset(stick, 0, sizeof(stick));
memset(visit, 0, sizeof(visit));
sum = 0;
int max = -1;
for (int i = 0; i < m; i++)
{
cin >> stick[i];
sum += stick[i];//求相应木棍长度的总和
if (stick[i] > max)max = stick[i];
}
if (max > sum / 4||m<4||sum%4!=0)
cout << "no" << endl;
else
{
sort(stick, stick + m);//将木棍长度进行排序,木棍越短灵活度越高
sum = sum / 4;//计算边长
if (bfs(m - 1, 0, 0))
{
cout << "yes" << endl;
}
else
{
cout << "no" << endl;
}
}
}
getchar();
getchar();
return 0;
}
1、本题关键在于理解剪枝的过程,判断是否能够构成正方形,有三种过程可以剪枝,1、若木棍的总数小于4, 2、木棍长度的总和是否可以整除4 3、最大木棍的长度是否大于边长
2、本题中要求的是将所有的木棍使用完全,因为木棍长度越小,活动性越高,所以访问木棍长度时,先进行排序,当满足可以组成三条边时,第四条边可自动满足
3、递归函数的设置,引入一个变量记录组成当前这条边已有的长度,若满足边长,则将该变量清空,继续记录下一条边寻找过程,若不满足,则继续进行寻找,知道满足边长要求为止
4、关键注意理解利用木棍长度匹配边长的过程