zoukankan      html  css  js  c++  java
  • 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
    ", len);
    56                 break; 
    57             } 
    58         }
    59     }
    60     return 0;
    61 }
    POJ1011 Sticks
     
  • 相关阅读:
    【BZOJ2138】stone
    【ARC076F】 Exhausted
    [SDOI2018]战略游戏
    CF536D Tavas in Kansas
    [JSOI2018]战争
    ###学习《C++ Primer》- 5
    ###学习《C++ Primer》- 4
    ###Linux基础
    ###Linux基础
    ###Linux基础
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/7356482.html
Copyright © 2011-2022 走看看