POJ1011 Sticks

木棒
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 147267   Accepted: 34890

Description

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

Input

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

Output

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

Sample Input

9
5 2 1 5 2 1 5 2 1
4
1 2 3 4
0

Sample Output

6
5

Source

Translator

北京大学程序设计实习, Xie Di
 
【题解】

搜索思路:枚举最终的木棒长度len,计算出木棒的根数cnt,依次搜索每根木棒由哪些木棍组成。
剪枝一(搜索顺序):木棍长度从大到小排序,先尝试长的木棍,同时每根木棒上的木棍也应该是按照长度递减的
剪枝二(枚举可行性):从小到大枚举最终木棒长度,只有该长度是长度总和的约数时才进行搜索
剪枝三(重复冗余剪枝):记录当前刚搜完的木棍长度,若搜索失败,当前木棒不再尝试同样长度的其它木棍
剪枝四(搜索可行性):如果在一个尚未包含任何木棍的木棒中,尝试搜索当前最长的木棍失败,直接返回。
                                  ——by 李煜东

实验证明这四个剪枝缺一不可(mmp)

 

 1 #include <iostream>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <cstdio>
 5 #include <algorithm>
 6 #define max(a, b) ((a) > (b) ? (a) : (b))
 7 
 8 inline void read(int &x)
 9 {
10     x = 0;char ch = getchar(), c = ch;
11     while(ch < '0' || ch > '9')c = ch, ch = getchar();
12     while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();
13     if(c == '-')x = -x;
14 }
15 
16 const int INF = 0x3f3f3f3f;
17 const int MAXN = 5000 + 5;
18 
19 int n,num[MAXN],len,sum,b[MAXN],cnt[MAXN],ma,step;
20 
21 //到第now根,最后一个长度是num[last]  - 1
22 int dfs(int now, int last)
23 {
24     if(now > step)return 1;
25     if(cnt[now] == len)return dfs(now + 1, 1);
26     int pre = 0;
27     for(register int i = last;i <= n;++ i)
28     {
29         if(b[i] || cnt[now] + num[i] > len || num[pre] == num[i])continue;
30         cnt[now] += num[i],b[i] = 1;
31         if(dfs(now, i + 1))return 1;
32         cnt[now] -= num[i],b[i] = 0;
33         pre = i;
34         if(cnt[now] == 0)return 0;
35     }
36     return 0;
37 }
38 
39 int main()
40 {
41     for(;;)
42     {
43         memset(cnt,0,sizeof(cnt)),sum=0,len=0,memset(b,0,sizeof(b)),ma = 0;
44         read(n);
45         if(!n)break;
46         for(register int i = 1;i <= n;++ i)
47             read(num[i]), sum += num[i], ma = max(ma, num[i]);
48         std::sort(num + 1, num + 1 + n, std::greater<int>());
49         for(len = ma;len <= sum;++ len)
50         {
51             if(sum % len)continue;
52             step = sum/len;
53             if(dfs(1, 1))
54             {
55                 printf("%d\n", len);
56                 break; 
57             } 
58         }
59     }
60     return 0;
61 }
POJ1011 Sticks

 

 

 

 
posted @ 2017-08-14 10:36  嘒彼小星  阅读(115)  评论(0编辑  收藏  举报