POJ 1011 DFS的经典问题

来源:互联网 发布:linux下安装pycharm 编辑:程序博客网 时间:2024/06/04 19:08
Sticks
Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 101433 Accepted: 23065

Description

George took sticks of the same length and cut them randomly until all parts became at most 50 units long. Now he wants to return sticks to the original state, but he forgot how many sticks he had originally and how long they were originally. Please help him and design a program which computes the smallest possible original length of those sticks. All lengths expressed in units are integers greater than zero.

Input

The input contains blocks of 2 lines. The first line contains the number of sticks parts after cutting, there are at most 64 sticks. The second line contains the lengths of those parts separated by the space. The last line of the file contains zero.

Output

The output should contains the smallest possible length of original sticks, one per line.

Sample Input

95 2 1 5 2 1 5 2 141 2 3 40

Sample Output

65

Source

Central Europe 1995
DFS的入门级经典问题,可以看出DFS的本质是用循环来遍历每一个根节点,用递归来加深搜索层数,找到符合条件的点就继续下一次搜索,否则触底反弹至上一层,重新换一个上层节点进行搜索,需要注意的是DFS的时间复杂度是O(M^N),(M是第一层的根节点个数),所以往往 强力的剪枝才能保证不超时;
以本题为例,存在以下剪枝:
1.棒长不是总长约数的棒不用搜索;
2.已组成某根大棒的小棒不参与组成下一根大棒的搜索;
3.如果某根小棒和之前已确定不能组成一根大棒的小棒长度相同,此棒pass;
4.最后对小棒长度从大到小进行排序,可以提高搜索的效率;
ps:以下代码参考自我认为编程风格很好的前辈之手,希望大家共同学习进步。 
#include<iostream>using namespace std;int stick[65];bool visit[65];int goal,sum,n;int cmp(const void *a,const void *b){return *((int *)b)-*((int *)a);}bool dfs(int now,int pos,int cnt){if(cnt*goal==sum) return true;for(int m=pos;m<n;m++){if(visit[m]||(m&&!visit[m-1]&&stick[m]==stick[m-1])) continue;//如果该棒已被搜索,或前一根棒无法成为组成第i根大棒if(now+stick[m]==goal)                                     //中的一根,而这根棒长度与之相同,继续搜索下一根棒{    visit[m]=true;     if(dfs(0,0,cnt+1)) return true;     visit[m]=false;//如果某些棒可以组成一根大棒,但接下来的棒子组不出与之相同的大棒长度,继续搜索下一根棒     return false;   }else if(now+stick[m]<goal){visit[m]=true;if(dfs(now+stick[m],m+1,cnt))return true;        visit[m]=false;//如果该棒无法和后续的棒子组成一根大棒的长度,继续搜索下一根棒if(now==0) return false;}//如果无法组成当前大棒长度,退出本次搜索}return false;}int main(){int i;while(cin>>n){if(n){sum=0;for(i=0;i<n;i++){cin>>stick[i];sum+=stick[i];}qsort(stick,n,sizeof(int),cmp);memset(visit,false,sizeof(visit));for(goal=stick[0];goal<=sum;goal++){if(sum%goal==0){if(dfs(0,0,0)){cout<<goal<<endl;break;}}    elsecontinue;}}elsebreak;}return 0;}

原创粉丝点击