题目大意:

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

一开始做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. Myeclipse优化篇

    1 . window-preferences-MyEclipse Enterprise Workbench-Maven4MyEclipse-Maven ,将 Maven JDK 改为电脑上安装的 JD ...

  2. (一)stm32之CMSIS标准、库目录、GPIO

    一.CMSIS标准 ST公司的stm32采用的是cortex-m3内核,内核是整个微处理器的CPU.该内核是ARM公司设计的一种处理器体系架构.内核与外设的关系就像PC上的CPU与硬盘.主板.内存等的 ...

  3. C++——使用类

    一.运算符重载 1.运算符重载 C++允许将运算符重载扩展到用户定义的类型. 要重载运算符,需使用被称为运算符函数的特殊函数形式.运算符函数的格式如下: operatorop(argument lis ...

  4. 青云的机房组网方案(简单+普通+困难)(虚树+树形DP+容斥)

    题目链接 1.对于简单的版本n<=500, ai<=50 直接暴力枚举两个点x,y,dfs求x与y的距离. 2.对于普通难度n<=10000,ai<=500 普通难度解法挺多 ...

  5. JAVA 程序设置运行内存

    1.修改jdk设置 2.如果不行则 一般安装完eclipse之后,在安装目录下你应该可以看到有一个 eclipse.ini 文件,对了,就是在这个文件里面修改 -vmargs:说明后面是VM的参数 - ...

  6. CentOS Linux iptables 防火墙

    快速安装,配置,启动,检查 - 关闭 5002 - 5011 端口开放所有其它 yum install iptables iptables -F iptables -X iptables -Z ipt ...

  7. html文本框(input)不保存缓存记录

    有的时候js往文本框里赋值,结果在火狐中刷新后,刚才赋的值还在,导致好多麻烦的事情,现总结一下解决办法如下: <input name="bestlovesky"  type= ...

  8. 【转】 Android自定义捕获Application全局异常

    大家都知道,现在安装Android系统的手机版本和设备千差万别,在模拟器上运行良好的程序安装到某款手机上说不定就出现崩溃的现象,开发者个人不可能购买所有设备逐个调试,所以在程序发布出去之后,如果出现了 ...

  9. cocos2dx从入门到精通课程

    一.移动开发基础 二.cocos2dx跨平台理论 三.cocos2dx框架 四.cocos2dx内存管理 五.cocos2dx的事件与消息机制 六.cocos2dx的定时器 七.cocos2dx的渲染 ...

  10. css读书笔记3:定位元素

    定位元素要掌握css技术,核心就是要掌握元素定位. 一般把下面这条规则作为所有css样式表的第一条,初始化所有元素的内边距和外边距都为0: * {padding:0;margin:0;} 盒模型浏览器 ...