北大poj-1011

Posted 靠谱一点就好

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了北大poj-1011相关的知识,希望对你有一定的参考价值。

木棒

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 136132   Accepted: 32036

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

 
方法:DFS+强剪枝
分析:经典的搜索问题,需要细细考虑剪枝条件,每一次的剪枝都能大幅度提升速度。
剪枝:
1. 首先将数据从大到小排序,搜索的时候从大到小搜索,这样才能保证数据的充分使用,而且对剪枝也很有帮助
2. 原始每根木条的长度是总长度的约数,所以搜索空间是总长度的约数
3. 检索的时候,用最长木条的长度作为搜索的起始长度
4. 如果stick[i] == stick[i+1],且stick[i]匹配失败,那么stick[i+1]必然也是失败的
5. 如果第i组的第一根木条(也是最长的)在匹配过程中失败,那么就直接返回第i-1组重新匹配。因为第i组的组合一定是最长木条的子集。
 
  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 
  5 #define MAX_NUM 64
  6 #define FAILURE 1
  7 #define SUCCESS 0
  8 
  9 int gwStickNum = 1;
 10 int gwtotalLen;
 11 int gwData[MAX_NUM];
 12 int gwSelect[MAX_NUM];
 13 int gwGroup;
 14 
 15 void sort(int *a, int left, int right)
 16 {
 17     if(left >= right)
 18     {
 19         return;
 20     }
 21     int i = left;
 22     int j = right;
 23     int key = a[left];
 24     while(i < j)
 25     {
 26         while(i<j && key>=a[j])
 27         {
 28             j--;
 29         }
 30         a[i] = a[j];
 31         while(i<j && key<=a[i])
 32         {
 33             i++;
 34         }
 35         a[j] = a[i];
 36     }
 37     a[i] = key;
 38     sort(a, left, i-1);
 39     sort(a, i+1, right);
 40 }
 41 
 42 int match(int goal, int sum, int nowGroup)
 43 {
 44     int i = 0;
 45     if(sum > goal) return FAILURE;
 46     if(sum == goal)
 47     {
 48         nowGroup++;
 49         if(nowGroup == gwGroup) return SUCCESS;
 50         sum = 0;
 51         return match(goal, sum, nowGroup);
 52     }
 53     for(i=1; i<gwStickNum; i++)
 54     {
 55         if(gwSelect[i] == 1) continue;
 56         sum += gwData[i];
 57         gwSelect[i] = 1;
 58         if(SUCCESS == match(goal, sum, nowGroup)) return SUCCESS;
 59         gwSelect[i] = 0;
 60         sum -= gwData[i];
 61         if(sum == 0) return FAILURE;
 62         while(gwData[i] == gwData[i+1] && i < gwStickNum)
 63         {
 64             i++;
 65         }
 66     }
 67     return FAILURE;
 68 }
 69 
 70 int searchFactors(int start)
 71 {
 72     int i = 0;
 73     for(i=start+1; i<=gwtotalLen; i++)
 74     {
 75         if(gwtotalLen % i ==0) return i;
 76     }
 77     return 0;
 78 }
 79 
 80 int calc()
 81 {
 82     int sum = gwData[0];
 83     int Len = 0;
 84     gwSelect[0] = 1;
 85     int start = gwData[0]-1;
 86     while(start < gwtotalLen)
 87     {
 88         Len = searchFactors(start);
 89         gwGroup = gwtotalLen / Len;
 90         if(SUCCESS == match(Len, sum, 0)) return Len;
 91         start = Len;
 92         memset(gwSelect, 0, sizeof(gwSelect));
 93         gwSelect[0] = 1;
 94         sum = gwData[0];
 95     }
 96     return 0;
 97 }
 98 
 99 int getTatolLen(int *a, int arryLen)
100 {
101     int i = 0;
102     int sum = 0;
103     for(i=0; i<arryLen; i++)
104     {
105         sum += a[i];
106     }
107     return sum;
108 }
109 
110 int main(void)
111 {
112     int i = 0;
113     int result = 0;
114     while(scanf("%d", &gwStickNum), gwStickNum != 0)
115     {
116         for(i=0; i<gwStickNum; i++)
117         {
118             scanf("%d", &gwData[i]);
119         }
120 
121         gwtotalLen = getTatolLen(gwData, gwStickNum);
122         sort(gwData, 0, gwStickNum-1);
123         result = calc();
124 
125         printf("%d\n", result);
126         memset(gwSelect, 0 , sizeof(gwSelect));
127     }
128 
129     return 0;
130 }
测试数据:
9
15 3 2 8 8 4 11 8 1
0

20
------------------------------------------------------
27
15 3 2 4 11 1 8 8 8 15 3 2 4 11 1 8 8 8 15 3 2 4 11 1 8 8 8
0

20
------------------------------------------------------
9
5 2 1 5 2 1 5 2 1
4
1 2 3 4
0

6
5
------------------------------------------------------
46
40 37 32 10 47 4 42 56 61 23 59 36 27 16 16 37 26 19 14 29 31 58 51 32 63 28 11 25 12 15 39 42 46 43 11 19 53 17 39 21 45 44 8 23 51 55 
58
57 6 44 4 16 35 54 9 32 23 43 55 46 41 8 41 55 44 31 59 57 58 59 29 53 30 3 39 52 17 32 45 8 40 34 18 20 11 32 33 14 41 31 25 4 42 54 9 29 37 47 29 34 20 47 56 61 5 
26
3 64 18 49 4 40 18 61 50 36 17 49 8 17 62 11 24 8 36 59 34 26 28 7 37 26 
0

89
89
99

 

以上是关于北大poj-1011的主要内容,如果未能解决你的问题,请参考以下文章

POJ 1011 Sticks DFS 剪枝

POJ 1011 Sticks

poj1011 Sticks

poj1011(DFS+剪枝)

POJ1011 SticksDFS+剪枝

poj-1011 sticks(搜索题)