Sticks
Time Limit: 1000MS
Memory Limit: 10000K
Total Submissions: 93302
Accepted: 20906
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
9 5 2 1 5 2 1 5 2 1 4 1 2 3 4 0
Sample Output
6 5
这个问题几个剪枝条件都非常关键 不然就会TLE。自己腐朽的脑子不够用,在网上找了一些剪枝的条件。
题目大意:给出一些长度不大于 50 的木棍, 要求你把这些小木棍拼成 长度相同木棍,当然长度越小越好
剪枝技巧:
- 将输入的木棍长度从大到小排列。直白地说,原因是匹配时用一支长度为K的木棍比用几个短的小木棍拼成的要好。因为短木棍有更高的灵活性,在接下来的匹配中可能发挥更加重要的作用。举个例子,那题目中的第一种输入来说,如果我在匹配时将2,2,1,1用作一组匹配,那么就无法构造出最短长度为6的解。
- 开始搜索一支长度为K的木棍时,总是从当前最长的未使用木棍开始,如果搜索匹配不成功的话,那么其他的方法肯定也不能成功。因为每一个木棍都必须被用到。这个剪枝条件如果不用就会TLE。
- 相同长度的木棍避免多次搜索。这个剪枝如果不用倒不会造成TLE。
1: //#define DEBUG
2: #include <iostream>
3: #include <cstdio>
4: #include <cstring>
5: #include <cstdlib>
6: //#include <windows.h>
7: int n;
8: int stnum;
9: int segment[70];
10: int visit[70];
11: int maxv;
12: bool flag;
13: using namespace std;
14: int Compare(const void *elem1, const void *elem2)
15: {
16: return -*((int *)(elem1)) + *((int *)(elem2)); //降序排序
17: }
18: bool dfs(int sticknumber, int curlen, int pos,int sticklen )
19: {
20: if(sticknumber == stnum)
21: return true;
22: for(int i = pos+1;i<n;++i)
23: {
24: if(visit[i] == 0 && curlen+segment[i] == sticklen)
25: {
26: visit[i] = 1;
27: if(dfs(sticknumber+1,0,-1,sticklen))
28: return true;
29: visit[i] = 0;
30: return false; //大的都不行,用小的凑起来更加不行
31: }
32: else if(visit[i] == 0 && curlen+ segment[i] < sticklen)
33: {
34: visit[i] = 1;
35: if(dfs(sticknumber,curlen+segment[i],i,sticklen))
36: return true;
37: visit[i] = 0;
38: if(curlen==0) return false; // 当前这个是最大的 并且以它开始匹配没有找到答案 肯定不行
39: while(segment[i] == segment[i+1]) i++;
40: }
41: }
42: return false;
43:
44: }
45: int main()
46: {
47: #ifdef DEBUG
48: freopen("test.txt","r",stdin);
49: freopen("result.txt","w",stdout);
50: #endif
51: while(scanf("%d",&n) && n)
52: {
53: int sum = 0;
54: maxv = 0;
55: for(int i=0;i<n;++i)
56: {
57: scanf("%d",segment+i);
58: if(segment[i] > maxv)
59: maxv = segment[i];
60: sum+=segment[i];
61: }
62: qsort(segment, n, sizeof(int), Compare);
63: for(int i=maxv;i<=sum;++i)
64: {
65: if(sum%i ==0)
66: {
67: memset(visit,0,sizeof(visit));
68: stnum = sum/i;
69: if(dfs(0,0,-1,i))
70: {
71: printf("%d\n",i);
72: break;
73: }
74: }
75: }
76: }
77: #ifdef DEBUG
78: freopen( "CON", "w", stdout );
79: system("result.txt");
80: #endif
81: }