1.题目链接。题目的意思十分简单,就是给你一些木棒以及这些木棒的长度,问他们能不能拼成一个正方形。看到这个问题,我们首先想到的是这些木棒的总和一定要是4的倍数,否则一定是不可行的。但是就算是判断了是4的倍数,之后该怎么办呢?我们可以采用dfs搜索解决这个问题。dfs的参数:cur,pos,res.我们首先明确一个问题,如果这些数据满足条件,我们拼完3条边就行了,最后一条边一定是成立的。所以我们dfs就是对每一条边dfs,我们搜索的目的就是为了拼好每一条边。cur就是代表了拼好了多少条边,pos代表现在在用那一个木棒,res是什么呢?我们直到每一条边的长度是周长的4分之一,我们dfs的目的就是拼好每一条边。所以res代表的就是我们当前正在拼的这一条边还需要多少。dfs很重要的就是关于递归出口的确定,我们刚才已经说了,cur=3即可结束。那么剩下的状态如何转移?假设我们现在面临的木棒的长度是s,如果res=s,那么把这个木棒加入到cur这条边,cur+1,pos=0,res=goal.进行下一条边的操作。如果s<res,那么这条边依然加进来,但是cur不变,pos+1.res-s.继续进行下一轮搜索。分析好了这些,代码一经写完了。代码如下,不懂得再模拟一下就明白了。AC了之后看其他大佬的代码,发现他们都有对长度排序,我不是很理解为什么要排序,可能是因为想在遍历的时候尽快的找到符合的长度。
#include"stdafx.h"
#include<iostream>
#include<cstring>
#include<algorithm>
#pragma warning(disable:4996)
using namespace std;
const int N = 25;
int a[N];
int used[N];
int goal = 0;
int t;
bool cmp(int a, int b)
{
return a > b;
}
bool dfs(int cur, int pos, int res)
{
if (cur == 3)
{
return true;
}
for (int i = pos; i < t; i++)
{
if (used[i])continue;
used[i] = 1;
if (a[i] == res)
{
if (dfs(cur + 1, 0, goal))
{
return true;
}
}
if (a[i] < res)
{
if (dfs(cur, i + 1, res - a[i]))
{
return true;
}
}
used[i] = 0;
}
return false;
}
int main()
{
int T;
scanf("%d", &T);
int sum=0;
while (T--)
{
int sum = 0;
scanf("%d", &t);
for (int i = 0; i < t; i++)
{
scanf("%d", &a[i]);
sum += a[i];
}
if (sum % 4 != 0)
{
puts("no");
continue;
}
goal = sum / 4;
memset(used, 0, sizeof(used));
if (dfs(0, 0, goal))
{
puts("yes");
}
else
{
puts("no");
}
}
}