DFS —— 剪枝+记忆化搜索
剪枝不难想到:
每次只需搜索长度小于或等于当前木棍的木棍。
可我一开始一直WA,WA到怀疑人生。。。
于是贴网上代码,写对拍。但随机生成的数据太弱不好拍出来。
于是四处百度找特殊数据。
还真让我在 POJ 找到了。
1
14 1 4 5 5 9 10 10 12 15 16 17 17 19 20
一种可行解为 :
(20 15 5 ),(19 17 4 ),( 17 12 10 1 ), ( 16 10 9 5 )
审视后发现一开始写的dfs传递参数只有当前木棍长度和搜索位置。
原程序会处理成:
(20 19 1) (17 10 9 4) (17 …
然后就判定无法构成四边形。
所以需要多加已完成边数这一参数。
代码:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define N 111111
using namespace std;
bool vis[N];
int s[N] , alen , n;
bool dfs (int len,int loc,int cnt)
{
if (len == 0)
{
if (cnt+1 == 4)
return true;
return dfs(alen,n,cnt+1);
}
for (int i=loc;i>0;i--)
if (s[i] <= len && !vis[i])
{
vis[i] = true;
if (dfs(len-s[i],i,cnt))
return true;
else
vis[i] = false;
}
return false;
}
int main ()
{
//freopen ("input.txt","r",stdin);
//freopen ("output.txt","w",stdout);
int T;
scanf ("%d",&T);
while (T--)
{
memset (vis,0,sizeof(vis));
scanf ("%d",&n);
alen = 0;
for (int i=1;i<=n;i++)
{
scanf ("%d",&s[i]);
alen += s[i];
}
sort (s+1,s+n+1);
if (alen%4 || n<4)
{
printf ("no\n");
continue;
}
alen /= 4;
bool flag = dfs(alen,n,0);
if (flag)
printf ("yes\n");
else
printf ("no\n");
}
return 0;
}
/*
1
14 1 4 5 5 9 10 10 12 15 16 17 17 19 20
*/