【转】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; }