一、Description

乔治拿来一组等长的木棒,将它们随机地砍断,使得每一节木棍的长度都不超过50个长度单位。然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度。请你设计一个程序,帮助乔治计算木棒的可能最小长度。每一节木棍的长度都用大于零的整数表示。

Input

输入包含多组数据,每组数据包括两行。第一行是一个不超过64的整数,表示砍断之后共有多少节木棍。第二行是截断以后,所得到的各节木棍的长度。在最后一组数据之后,是一个零。

Output

为每组数据,分别输出原始木棒的可能最小长度,每组数据占一行。

二、问题分析

网上找到的题解,很棒:http://www.cppblog.com/y346491470/articles/155318.html

【题解】:下面说下几个重要的剪枝:

1.把所有木棍的长度从大到小排列,组合木棒时优先使用长的木棍,这样可以加快组合速度,并且对后面的剪枝有帮助。

2.木棒的长度一定是大于等于最长木棍的长度并且小于等于所有木棍长度的和,这个很容易证明。

3.木棒的长度一定是所有木棍长度的和的约数,这个也很容易证明。

4.在某一个木棒的组合过程中,对于当前的木棍stick[i],如果stick[i-1]没有被组合并且stick[i] == stick[i-1],那么不用考虑stick[i],显然stick[i]最终也不会被组合。

5.如果此次是在尝试第i个木棒的第一段,假设stick[j]为当前可以被使用的最长的木棍,如果此次组合失败,直接退出搜索,即退回到对第i-1个木棒的搜索。试想:失败说明现在使用stick[j]是不可行的,那么以后无论什么时候使用stick[j]都是不可行的,因为以后再处理stick[j]时可使用的木棍一定是当前可使用的木棍的子集,在更多木棍选择的情况下都不能组合成功,那么,在更少木棍选择的情况下一定不能组合成功。

三、问题解决

第一次听到“剪枝”:没有 正式的解释,大概意思是:就是在做搜索的时候,当你确定某些决策一定不可能得到答案的时候,就不必再搜索这个决策了,这样可以减少搜索量,加快程序速度,对于具体的问题是需要一些技巧的,最常见的就是可行性剪枝(当前状态一定不会出解)和最优性剪枝(当前状态即使出解了也一定不会最优)了。

这个问题涉及到排序和搜索算法,我用了QS和DFS。

import java.util.Scanner;

public class N1011_Sticks{

	static int[] sticks;
static boolean[] visited;
static int n;
static int st; public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
while ((n = scan.nextInt()) != 0) {
int sum = 0;
sticks = new int[n];
visited = new boolean[n];
for (int i = 0; i < n; i++) {
sticks[i] = scan.nextInt();
sum += sticks[i];
}
quicksort(0, n - 1);
boolean flag = false;
for (int ini = sticks[0]; ini < sum; ini++) {
if (sum % ini == 0 && dfs(0, 0, ini, 0)) {
System.out.println(ini);
flag = true;
break;
}
}
if (!flag) {
System.out.println(sum);
}
}
} static boolean dfs(int len, int s, int ini, int am) {
if (am == n) {
return true;
} int sp = -1; for (int i = s; i < n; i++) {
if (visited[i] || sticks[i] == sp) {
continue;
}
visited[i] = true;
if (len + sticks[i] < ini) {
if (dfs(len + sticks[i], i, ini, am + 1)) {
return true;
} else {
sp = sticks[i];
}
} else if (len + sticks[i] == ini) {
if (dfs(0, 0, ini, am + 1)) {
return true;
} else {
sp = sticks[i];
}
} visited[i] = false; if (len == 0) {
return false;
}
}
return false;
} static void quicksort(int p, int r) {
if (p < r) {
int a = part(p, r);
quicksort(p, a - 1);
quicksort(a + 1, r);
}
} static int part(int p, int r) {
int x = sticks[r];
int i = p - 1;
int j = p;
for (; j < r; j++) {
if (sticks[j] > x) {
i++;
int k = sticks[i];
sticks[i] = sticks[j];
sticks[j] = k;
}
}
int k = sticks[i + 1];
sticks[i + 1] = sticks[j];
sticks[j] = k;
return i + 1;
}
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

Poj_1011_Sticks(剪枝)的更多相关文章

  1. α-β剪枝算法的java语言实现(非常实用)

    利用α-β剪枝算法,对下图所示的博弈树进行搜索,搜索得到根节点选择的走步,以及没有必要进行评估的节点,并求出给出在何处发生了剪枝,以及剪枝的类型(属于α剪枝还是β剪枝). 注:□表示MIN节点:○表示 ...

  2. Sicily 1153: 马的周游问题(DFS+剪枝)

    这道题没有找到一条回路,所以不能跟1152一样用数组储存后输出.我采用的方法是DFS加剪枝,直接DFS搜索会超时,优化的方法是在搜索是优先走出度小的路径,比如move1和move2都可以走,但是如走了 ...

  3. HDU5887 Herbs Gathering(2016青岛网络赛 搜索 剪枝)

    背包问题,由于数据大不容易dp,改为剪枝,先按性价比排序,若剩下的背包空间都以最高性价比选时不会比已找到的最优解更好时则剪枝,即 if(val + (LD)pk[d].val / (LD)pk[d]. ...

  4. HDU5937 Equation(DFS + 剪枝)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5937 Description Little Ruins is a studious boy, ...

  5. alpha-beta剪枝搜索

    •一种基于剪枝( α-βcut-off)的深度优先搜索(depth-first search). •将走棋方定为MAX方,因为它选择着法时总是对其子节点的评估值取极大值,即选择对自己最为有利的着法: ...

  6. POJ1190生日蛋糕[DFS 剪枝]

    生日蛋糕 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 18236   Accepted: 6497 Description ...

  7. *HDU1455 DFS剪枝

    Sticks Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  8. HDU1010 DFS+剪枝

    Tempter of the Bone Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Othe ...

  9. HDU 5113 dfs剪枝

    题意:告诉格子规格,颜色个数,以及每个颜色能涂得格子数目,问是否能够实现相邻两个格子的颜色数目不相同. 分析:因为数据很小,格子最多是5 * 5大小的,因此可以dfs.TLE了一次之后开始剪枝,31m ...

随机推荐

  1. GIT客户端的使用【原创】

    这次分享的方式,采用的是视频的形式,视频是本人录制. 在做项目使用SVN的时候经常有各种错误出现,所以萌发使用git的想法.在学习git的过程中发现一个神器就是分支,虽然在SVN里也有分支,但由于机制 ...

  2. CentOS 6.9上安装Mysql 5.7.18 安装

    CentOS 6.9上安装Mysql 5.7.18 安装 下载地址:https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.18-linux-g ...

  3. JQuery利用选择器定位动态id?

    假如我们需要去定位一个动态生成的div,我们需要为它指定一个动态的id 例如: 前台使用EL进行迭代LIST生成div,为其添加动态的id,生成之后变成下面样式 <div id="tz ...

  4. 史上最浅显易懂的Git教程1

    工作区(Working Directory)就是你在电脑里能看到的目录, 工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库. Git的版本库里存了很多东西,其中最重要的就是称为stag ...

  5. 前端编程提高之旅(三)----浏览器兼容之IE6

    在爱奇艺实习期间,乐帝主要负责移动端活动页面的制作,因为移动浏览器是随着智能手机兴起的,这就决定了移动端不会重蹈浏览器兼容问题的覆辙.一開始就比較好的支持web标准,而纵观整个互联网行业,移动web开 ...

  6. EasyNVR H5无插件摄像机直播解决方案前端解析之:videojs初始化的一些样式处理

    初始化完成对videojs样式的调整 由于不同项目的需要,对于加载出来的videojs播放器样式也有不同的需求:我们需要自主的处理一下加载出来的videojs播放器的样式: 默认加载出来的会包含有暂停 ...

  7. sql中decode()重要函数使用

    decode()函数简介: 主要作用:将查询结果翻译成其他值(即以其他形式表现出来,以下举例说明): 使用方法: Select decode(columnname,值1,翻译值1,值2,翻译值2,.. ...

  8. viewport详解

    本文主要讲解viewpor相关知识. 参考资料&内容来源 博客园:https://www.cnblogs.com/zaoa/p/8630393.html 博客园:http://www.cnbl ...

  9. Vector 源码阅读

    Vector在功能上与ArrayList是类似的,实现的数据结构也是一样的.但Vector是线程安全的,ArrayList是线程不安全的.

  10. 转载 j2ee j2se j2me 区别,mvc 和ssh联系理解

    [转]J2SE J2EE J2ME的区别 以及 MVC与SSH对应关系 2014-3-6阅读322 评论0 J2SE J2EE J2ME的区别多数编程语言都有预选编译好的类库以支持各种特定的功能,在J ...