【转】POJ-2362-Square:简单 DFS+剪枝
思路:
首先将输入的各边长累加求和 即四边形周长sum, 后除4 即边长side,这样 通过DFS 搜索这些sticks能否组合成4根长度均为side 进而确定yes no。
在此 就涉及到搜索顺序了-最优性剪枝: 不难理解 先搜索的小棒子 越长,组合构成side的方式就越少,搜索到结果的时间就越短。
SO从最长的棒子开始进行DFS。
// num表示已确认组合构成 的side的数目 即所求正方形的边数
// len表示所求正方形边长度 s表示搜索起点
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int N, M, sum, side;
bool DFS(int *sticks, bool *visited,\
int num, int len, int s)
{
if(num==3)//最优性剪枝 当搜索到3条边都满足时停止搜索
return true;
for(int i=s; i>=0; i--)
{
if(visited[i])
continue;
visited[i]=true;
if(len+sticks[i]<side)
{
if(DFS(sticks,visited,num,len+sticks[i],i))
return true;
}
else if(len+sticks[i]==side)
{
if(DFS(sticks,visited,num+1,0,M-1))
return true;
}
visited[i]=false;// 回溯 该边不满足当前side的组合
}
return false;
}
int main()
{
cin>>N;
while(N--)
{
cin>>M;
sum=0;
int *sticks=new int[M];
bool *visited=new bool[M];
for(int i=0; i<M; i++)
{
cin>>sticks[i];
visited[i]=false;
sum+=sticks[i];
}
sort(sticks,sticks+M);
side=sum/4;
if(sum%4!=0||sticks[M-1]>side)//可行性剪枝
{
cout<<"no"<<endl;
continue;
}
memset(visited,0,sizeof(visited));
if(DFS(sticks,visited,0,0,M-1))
cout<<"yes"<<endl;
else
cout<<"no"<<endl;
delete sticks;
delete visited;
}
return 0;
}

浙公网安备 33010602011771号