POJ 2362
知识点:dfs(深度优先搜索)
题解:基本的dfs搜索判断可行性问题。一般的dfs搜索,如果不加剪枝,复杂度是指数级的,所以必须要能发掘出优秀的剪枝条件;
在本题中,一般有如下剪枝:
①:所有线段的长度之和必须为4的倍数;
②:搜索之前,把所有线段按从大到小排序,因为长度越长,在拼凑时的灵活度就越低;
③:当能拼凑出3根等长的线段时,第四根就无须再搜了;
④:当用某一条线段无法得出可行解时,和它等长的,一样不可以;
有了以上四个剪枝条件,这题就可以过了;
add:这题理解之后可以去看看poj 1011,那题是本题的加强版,所以光凭以上4个剪枝还是无法通过,大家要接着发掘剪枝条件;
#include <iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<string>
#include<cmath>
#include<queue>
#define N 1005
#define M 10
#define MAXN 1000005
#define mod 1000000000
#define ll long long
using namespace std;
int n,T;
int a[N];
int flag;
int sum;
int ma;
int l;
int vis[N];
bool cmp(int x,int y)
{
return x>y;
}
int DFS(int done,int left,int cur)
{
// printf(" done=%d left=%d cur=%d\n",done,left,cur);
if(left==0){
if(done==3) return 1;
else{
if(DFS(done+1,l,1)==1) return 1;
else return 0;
}
}
else{
for(int i=cur;i<=n;i++){
if(vis[i]==1) continue;
if(a[i]>left) continue;
vis[i]=1;
if(DFS(done,left-a[i],i)==1) return 1;
else{
vis[i]=0;
int j=i+1;
while(j<=n && a[j]==a[i]){
j++;
}
i=j-1;
}
}
return 0;
}
}
int main()
{
int i,j,k;
// freopen("data.txt","r",stdin);
scanf("%d",&T);
//while(scanf("%d",&n)!=EOF)
while(T--)
// for(cnt=1;cnt<=T;cnt++)
{
scanf("%d",&n);
memset(vis,0,sizeof(vis));
sum=flag=0;ma=0;
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
sum+=a[i];
ma=max(a[i],ma);
}
if(sum%4!=0 || ma>sum/4){
printf("no\n");
continue;
}
l=sum/4;
sort(a+1,a+1+n,cmp);
vis[1]=1;
if(DFS(0,l-a[1],1)==1)
printf("yes\n");
else
printf("no\n");
}
return 0;
}