POJ 1011 Sticks

来源:互联网 发布:热传导有限元软件 编辑:程序博客网 时间:2024/04/28 21:05

Description

乔治拿来一组等长的木棒,将它们随机地砍断,使得每一节木棍的长度都不超过50个长度单位。然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度。请你设计一个程序,帮助乔治计算木棒的可能最小长度。每一节木棍的长度都用大于零的整数表示。

Input

输入包含多组数据,每组数据包括两行。第一行是一个不超过64的整数,表示砍断之后共有多少节木棍。第二行是截断以后,所得到的各节木棍的长度。在最后一组数据之后,是一个零。

Output

为每组数据,分别输出原始木棒的可能最小长度,每组数据占一行。

Sample Input

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

Sample Output

65

Source

Central Europe 1995

Translator

北京大学程序设计实习, Xie Di

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

dfs+剪枝~剪枝是关键~

主要的剪枝有:

1.从大到小排序,相同的长度如果已验证过不行就直接跳过;

2.范围从木棍最大长度maxx到总长tot,maxx和tot在输入的时候就记录下;


#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define max(u,v) u>v ? u:vint n,a[100],tot,maxx;bool b[65];bool dfs(int k,int u,int v)  //k长度u目前v总根数 {if((v+1)==(tot/k) && u==k) return 1;if(u==k) u=0,v++;for(int i=1;i<=n;i++){if(a[i]==a[i-1] && !b[i-1]) continue;if(!b[i] && (a[i]+u)<=k){  b[i]=1;if(dfs(k,u+a[i],v)) return 1;b[i]=0;}}return 0;}int main(){while(scanf("%d",&n)==1 && n){tot=0;maxx=0;for(int i=1;i<=n;i++) scanf("%d",&a[i]),tot+=a[i],maxx=max(maxx,a[i]);sort(a+1,a+n+1);for(int i=maxx;i<=tot;i++)  if((tot%i)==0)  {memset(b,0,sizeof(b));if(dfs(i,0,0)){  printf("%d\n",i);break;}  }}return 0;}




1 0
原创粉丝点击