题目传送门
1 /*
2 题意:若干小木棍,是由多条相同长度的长木棍分割而成,问最小的原来长木棍的长度;
3 DFS剪枝:剪枝搜索的好题!TLE好几次,终于剪枝完全!
4 剪枝主要在4和5:4 相同长度的木棍不再搜索;5 若新的搜索连第一条都没组合出来,直接break;
5 详细解释:http://blog.csdn.net/lyy289065406/article/details/6647960
6 http://www.cnblogs.com/devil-91/archive/2012/08/03/2621787.html
7 这题虐我千百遍,我待她如。。 656K 0MS
8
9
10 博客随笔第100篇,纪念一下:)
11 */
12 #include <cstdio>
13 #include <iostream>
14 #include <cstring>
15 #include <map>
16 #include <set>
17 #include <cmath>
18 #include <algorithm>
19 using namespace std;
20
21 const int MAXN = 66;
22 const int INF = 0x3f3f3f3f;
23 int a[MAXN];
24 bool vis[MAXN];
25 int sum;
26 int n, cnt;
27
28 bool cmp(int x, int y)
29 {
30 return x > y;
31 }
32
33 bool DFS(int len, int ans, int num, int s)
34 {
35 if (num == cnt) return true;
36
37 int pre = -1;
38 for (int i=s; i<=n; ++i)
39 {
40 if (vis[i] || a[i] == pre) continue; //Cut 4
41
42 vis[i] = true;
43 if (ans + a[i] < len)
44 {
45 if (DFS (len, ans + a[i], num, i) == true) return true;
46 else pre = a[i];
47 }
48 else if (ans + a[i] == len)
49 {
50 if (DFS (len, 0, num+1, 1) == true) return true;
51 else pre = a[i];
52 }
53 vis[i] = false;
54
55 if (ans == 0) break; //Cut 5
56 }
57
58 return false;
59 }
60
61 int main(void) //POJ 1011 Sticks
62 {
63 //freopen ("POJ_1011.in", "r", stdin);
64
65 while (scanf ("%d", &n) == 1 && n)
66 {
67 sum = 0; memset (vis, 0, sizeof (vis));
68 for (int i=1; i<=n; ++i)
69 {
70 scanf ("%d", &a[i]); sum += a[i];
71 }
72 sort (a+1, a+1+n, cmp); //Cut 1
73
74 bool flag = false;
75 for (int i=a[1]; i<=sum-i; ++i) //Cut 2
76 {
77 if (sum % i == 0) //Cut 3
78 {
79 cnt = sum / i;
80 if (DFS (i, 0, 0, 1) == true)
81 {
82 flag = true;
83 printf ("%d
", i); break;
84 }
85 }
86 }
87 if (!flag) printf ("%d
", sum);
88 }
89
90 return 0;
91 }
92
93 /*
94 6
95 5
96 */