题目大意:

乔治有一些碎木棒,是通过将一些相等长度的原始木棒折断得到的,给出碎木棒的总数和各自的长度,求最小的可能的原始木棒的长度;(就是将一些正整数分组,每组加起来和相等,使和尽可能小)

一开始做poj 32ms过,但uva3000 ms 都超时。。。而且poj discuss里给出了一组bT数据,最后uva 0.2sac的代码也跑了3 。4秒左右。discuss里的大牛据说什么奇偶性剪枝0.01ms过,可惜搜了半天也没找到具体方法。这题就这样过好了。。(参考各种空间博客才艰难ac。不过此题实在是太经典了,搜索学习剪枝必做)

对于这道题而言,剪枝的策略一般有下面6个:

①先将木棒长度从大到小进行排序,这样便于后面的选择和操作,是后面一些剪枝算法的前提。

②在枚举原木棒长度时,枚举的范围为max与sum/2之间,如果这个区间内没有找到合适的长度,那么最后原木棒的长度只能是sum。

③枚举的原木棒的长度只能是sum的约数。

④在深搜过程中,如果当前木棒和前一个木棒的长度是一样的,但是前一个木棒没有被选上,那么这个木棒也一定不会被选上。

⑤在深搜过程中,如果当前是在拼一根新木棒的第一截,但如果把可用的最长的一根木棒用上后不能拼成功的话,那么就不用再试后面的木棒了,肯定是前面拼的过程出了问题。

⑥在深搜过程中,如果当前可用的木棒恰好能补上一根原木棒的最后一截,但用它补上之后却不能用剩下的木棒完成后续的任务,那么也不用再试后面的木棒了,肯定是前面拼的过程出了问题。

参考博客:http://www.cnblogs.com/staginner/archive/2011/09/08/2171329.html

我的AC 代码:(剪枝见注释)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
 
int n,max_len,min_len,sum,ans,num,flag;
int a[10000],v[10000];
 
bool cmp(const int &x,const int &y)
{
     return !(x<y);
}
 
void search(int step,int from,int cur)//step表示当前去凑的是第几根原始棒,order表示当前用了多少根碎棒子来凑第step根
{
     //printf("%d %d\n",step,cur);
    if (cur==ans)
    {
       if (step==num)
       {
          flag=1;
          return;
       }
       int k;
       for (k=1;k<=n && v[k];k++);
       v[k]=1;
       search(step+1,1,a[k]);
       v[k]=0;
       return;
    }
    for (int i=from;i<=n;i++)
    {
        if (v[i])
           continue;
        if (cur+a[i]>ans)
           continue;
        if (a[i]==a[i-1] && !v[i-1])
           continue;//剪枝3:上一根棒和目前这根一样并且没用过,那么用这一根去凑和用上一根去凑结果一样都不能出解
        //printf("kk %d %d\n",cur,cur+a[i]);
        int t=a[i]+cur;
        if (t!=ans && t+min_len>ans)
           continue;
        v[i]=1;
        search(step,i+1,t);
        v[i]=0;
        if (t==ans)
           return;
        if (flag || cur==0)//剪枝4:如果当前用了1根碎棒子来凑,枚举了第一根碎棒不能出解那么跳出
           return;
    }
    return;
}
 
int main ()
{
    while (scanf("%d",&n)==1)
    {
          if (n==0)
             break;
          v[0]=1;
          a[0]=210000000;
          max_len=-1;
          min_len=21000000;
          sum=0;
          flag=0;
          for (int i=1;i<=n;i++)
          {
              scanf("%d",&a[i]);
              if (a[i]>max_len)
                 max_len=a[i];
              if (a[i]<min_len)
                 min_len=a[i];
              sum+=a[i];
          }
          sort(a+1,a+n+1,cmp);
          for (ans=max_len;ans<=sum/2;ans++)//剪枝1:答案的下界为最长的棒,上界为长度总和
          {
              if (sum%ans!=0)
                 continue;//剪枝 2:原始棒长度是总长度的约数
              for (int k=1;k<=n;k++)
                  v[k]=0;
              num=sum/ans;
              search(1,1,0);
              if (flag)
              {
                  printf("%d\n",ans);
                  break;
              }
          }
          if (!flag)
             printf("%d\n",sum);
    }
    return 0;
}

Sticks(poj1011/uva307)的更多相关文章

  1. poj1011 Sticks(DFS+剪枝)

    题目链接 http://poj.org/problem?id=1011 题意 输入n根棍子的长度,将这n根棍子组合成若干根长度相同的棍子,求组合后的棍子的最小长度.这题是poj2362的加强版,思路与 ...

  2. poj-1011 sticks(搜索题)

    George took sticks of the same length and cut them randomly until all parts became at most 50 units ...

  3. poj1011 Sticks (dfs剪枝)

    [题目描述] George took sticks of the same length and cut them randomly until all parts became at most 50 ...

  4. UVA-307 Sticks (DFS+剪枝)

    题目大意:用n根长度未必相等的木棒匹配出最多数量的等长木棒. 题目分析:枚举所有可能的等长木棒的长度,通过DFS的方式逐根匹配,在此过程中要剪枝.先将木棒长度按从大到小排序,也就是说匹配每一根等长木棒 ...

  5. 2018.07.03 POJ 2653 Pick-up sticks(简单计算几何)

    Pick-up sticks Time Limit: 3000MS Memory Limit: 65536K Description Stan has n sticks of various leng ...

  6. POJ2653:Pick-up sticks(线段相交)

    题目:http://poj.org/problem?id=2653 题意:题意很简单,就是在地上按顺序撒一对木棒,看最后有多少是被压住的,输出没有被压住的木棒的序号.(有点坑的就是没说清楚木棒怎么算压 ...

  7. Sticks(剪枝+BFS)

    Problem Description George took sticks of the same length and cut them randomly until all parts beca ...

  8. hdu 1455 Sticks(dfs+剪枝)

    题目大意: George有许多长度相同的木棍,随机的将这些木棍砍成小木条,每个小木条的长度都是整数单位(长度区间[1, 50]).现在George又想把这些小木棒拼接成原始的状态,但是他忘记了原来他有 ...

  9. 2015 CCPC D- Pick The Sticks(UESTC 1218) (01背包变形)

    http://acm.uestc.edu.cn/#/problem/show/1218 既然二维dp表示不了,就加一维表示是否在边界放置,放置一个,两个.有一个trick就是如果只放一根,那么多长都可 ...

随机推荐

  1. android MTK驱动背光唤醒流程

    在标准的android驱动中,睡眠唤醒流程非常清晰,能够较方便的更改lcd唤醒时间和led背光的点亮时间,但是也很容易出现问题,比如说闪屏,唤醒慢! 出现闪屏有两个原因 1. 开背光时间在唤醒lcd前 ...

  2. Java源码初学_LinkedList

    一.LinkedList的内部数据结构 LinkedList底层是一个链表的数据结构,采用的是双向链表,基本的Node数据结构代码如下: private static class Node<E& ...

  3. POJ 2385 Apple Catching

    比起之前一直在刷的背包题,这道题可以算是最纯粹的dp了,写下简单题解. 题意是说cows在1树和2树下来回移动取苹果,有移动次数限制,问最后能拿到的最多苹果数,含有最优子结构性质,大致的状态转移也不难 ...

  4. Selected SVN connector library is not available or cannot be loaded

    1.错误描述 The following data will be sent: ------ STATUS ------ pluginId            org.eclipse.team.sv ...

  5. 正则表达式使用(Js、Java)

    Js中全局替换,需要在最后加上g(global),并且使用//包围起来 1.全局替换字符+ 和 只替换第一个字符+ alert("2014+03-22++aaaa".replace ...

  6. shell中for循环

    shell中for循环总结 最常用的就是遍历操作某一类文件,比如批量建索引. for i in `ls` do samtools faidx $i done 注意:for末尾不需要冒号(:),循环的代 ...

  7. Perl 语法 - 基础

    perl语言的核心是正则表达式,在文本处理上非常有优势,与python类似,但语法不同,perl的语法很灵活,用多了才会觉得好用. 常用知识点总结: perl语法类似于C语言(perl源于Unix), ...

  8. dede调用文章的栏目,作者,发布时间.以及连接数据库输出一个表

    发布时间: {dede:field.pubdate function="MyDate('Y-m-d H:i',@me)"/}类目:{dede:field.typename/}发布人 ...

  9. 创建SSTP VPN,适应win7, 控制台导入证书

    1. 按 视窗+r 打开运行,运行 mmc命令 2.打开控制台窗口 3.在默认界面 按 Ctrl+m 快捷键 打开添加单元 窗口,然后在其左侧列表双击 证书 项 4.在打开的证书管理单元 第一步中选择 ...

  10. Matlab安装记录 - LED Control Activex控件安装

    Matlab安装记录-LED Control Activex控件安装 2013-12-01  22:06:36 最近在研究Matlab GUI技术,准备用于制作上位机程序:在Matlab GUI的技术 ...