poj 1011 Sticks 经典dfs+剪枝

来源:互联网 发布:幺正矩阵 编辑:程序博客网 时间:2024/05/17 02:13

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
题意:原来有一些长度相等的木棍,后来被随机的剪成了长度不超过50的片段,现在想要恢复,求能恢复的最小长度。

思路:能恢复的最大长度就是所有片段长度之和sum,最小长度大于等于片段的最大长度s,从s到sum开始枚举,枚举的每一个长度用dfs判断能不能拼出来。但这样可能会超时,所以得剪枝。

#include <cstdio>#include <algorithm>#include <cstring>using namespace std;#define maxn 100int st[maxn];int n,sum,len,total;bool used[maxn];bool cmp(int a,int b){return a>b;}bool dfs(int m,int k,int cnt){if(cnt==total) return true;for(int i=k;i<n;i++){if(used[i]) continue;if(m+st[i]==len) {used[i] = true;if(dfs(0,0,cnt+1)) return true;used[i] = false;return false;  //剪枝3:已经拼出来的部分+当前长度如果刚好等于枚举长度,这个长度后面如果不行的话那么就拼不出来 }else if(m+st[i]<len){used[i] = true;if(dfs(m+st[i],i,cnt)) return true;used[i] = false;if(m==0) return false; //剪枝4:如果一个都不行,那直接返回false while(st[i]==st[i+1]) i++;}}return false;}int main(){while(scanf("%d",&n) && n){sum = 0;for(int i=0;i<n;i++){scanf("%d",&st[i]);sum += st[i];}sort(st,st+n,cmp);  // 剪枝1:从大到小排序,大的拼不出来小的就不用拼了 for(len=st[0];len<=sum;len++){if(sum%len==0){  //剪枝2:整除 total = sum/len;memset(used,false,sizeof(used));if(dfs(0,0,0)){printf("%d\n",len);break;}}}}return 0;}




0 0