poj1011sticks题解

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 9 5 2 1 5 2 1 5 2 1 4 1 2 3 4 0 Sample Output 6 5

     题目要求将一系列的sticks重新组合,形成若干相等相等长度的木棒,且尽量使木棒长度最小,如果数据量比较小的话,就纯粹是搜索了,但题目要求的 sticks可能达到64根,如果纯粹的搜索则显然是会远远超过1000ms的,因而也就把剪枝放在了很重要的位置。从第一根stick开始,寻找下一根 stick使两者的长度小于等于木棒的长度,然后再寻找下一根stick,直到和为一根木棒的长度;然后又从一根没有被使用的stick开始进行下一根木棒的组合。概括一点说,就是一个深度优先搜索。
     算法很清晰,然而真正写起来却有不少要注意的地方.

     1.首先是used[]的恢复,当某一步搜索走不通的时候,不能忘记将used[i]置为false.

     2.其次是剪枝的采用,当第i步时,剩余最大的sticks[i]等于restLen时,继续搜索还是走不通的话,那么这一步取sticks[j],j>i也不会成功,所以此时返回false就行了。不然的话,会超时的。

#include #include #include using namespace std; int sticks[64]; bool used[64]; int stickNum; bool compare(int a, int b) { return a>b; } bool Dfs(int succeedNum,int restLen,int len) { if(succeedNum==stickNum && restLen==0) { return true; } if(restLen==0) { restLen = len; int i = 0; while(used[++i]); used[i] = true; bool ok = Dfs(succeedNum+1,restLen-sticks[i],len); if(ok) { return true; } else { used[i] = false; return false; } } else { for(int i=0;i vlen; while(cin>>stickNum &&stickNum>0) { for(int i=0;i>sticks[i]; } sort(sticks,sticks+stickNum,compare); int len = FindStickLen(); vlen.push_back(len); } for(int i=0;i

 

你可能感兴趣的:(POJ题解)