PKU1011:Sticks
木棒
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 70801 | Accepted: 15486 |
Description
乔治拿来一组等长的木棒,将它们随机地砍断,使得每一节木棍的长度都不超过50个长度单位。然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度。请你设计一个程序,帮助乔治计算木棒的可能最小长度。每一节木棍的长度都用大于零的整数表示。
Input
输入包含多组数据,每组数据包括两行。第一行是一个不超过64的整数,表示砍断之后共有多少节木棍。第二行是截断以后,所得到的各节木棍的长度。在最后一组数据之后,是一个零。
Output
为每组数据,分别输出原始木棒的可能最小长度,每组数据占一行。
Sample Input
95 2 1 5 2 1 5 2 141 2 3 40
Sample Output
65
原题地址:http://acm.pku.edu.cn/JudgeOnline/problem?id=1011&lang=default&change=true
____________________________________________________________________________________________________________________________
题解:
暴力搜索
重要的是剪枝,如何强力地减掉无用的搜索,本题中有一个很重要的条件,就是每根木棍必然会被用到。
代码
1 #include<stdio.h>
2 int len[65];
3 int tag[65];
4 int n,sum,i,l;
5 void swap(int a,int b)
6 {
7 int temp;
8 temp=len[a];
9 len[a]=len[b];
10 len[b]=temp;
11 }
12 void qsort(int l,int r)
13 {
14 int i,j,x;
15 x=len[r];
16 i=l-1;
17 for (j=l;j<r;j++)
18 if (x<len[j])
19 {
20 i++;
21 swap(i,j);
22 }
23 swap(i+1,r);
24 if (i>l) qsort(l,i);
25 if (i+2<r) qsort(i+2,r);
26 }
27 int search(int l,int a,int b,int ll)//拼第a根,一共用了b部分,当前长度ll
28 {
29 int i,done;
30 done=0;
31 if (b==n)
32 {
33 if (ll==0) return 1;
34 else return 0;
35 }
36 for (i=1;i<=n;i++)
37 {
38 if (len[i]==len[i-1]&&tag[i-1]==0) continue;//剪枝,两个一样的话,前面一个不行,后面一个肯定也不行。
39 if (tag[i]==0&&len[i]<=l-ll)
40 {
41 tag[i]=1;
42 if (len[i]==l-ll)
43 {
44 done=search(l,a+1,b+1,0);
45 tag[i]=0;
46 break;//剪枝,当长度正好时就没必要考虑比它小的了。
47 }
48 else
49 done=search(l,a,b+1,ll+len[i]);
50 tag[i]=0;
51 if (done==1) break;
52 if (ll==0) break;//剪枝,如果ll=0,那么一定是刚开始拼一根新棍,由于这些整棍不计顺序,如果l真的是可行解,那么这一步中从零开始找到的第一个未被用过的小木棍段一定可以在此时用上,而且做完直接break就好了。
53 }
54 }
55 return done;
56 }
57 int main()
58 {
59 scanf("%d",&n);
60 while (n)
61 {
62 sum=0;
63 for (i=1;i<=n;i++)
64 {
65 scanf("%d",&len[i]);
66 sum=sum+len[i];
67 }
68 qsort(1,n);
69 l=len[1];
70 for (i=1;i<=n;i++)
71 tag[i]=0;
72 while (sum%l!=0) l++;
73 while (search(l,1,0,0)==0)
74 {
75 for (i=1;i<=n;i++) tag[i]=0;
76 l++;
77 while (sum%l!=0) l++;
78 }
79 printf("%d\n",l);
80 scanf("%d",&n);
81 }
82 return 0;
83 }