hdu 1455 Sticks(dfs+剪枝)
题目大意:
George有许多长度相同的木棍,随机的将这些木棍砍成小木条,每个小木条的长度都是整数单位(长度区间[1, 50])。现在George又想把这些小木棒拼接成原始的状态,但是他忘记了原来他有多少根木棍,也忘记了木棍的长度。现在请你编写一个程序,找到最短的原始的木棍长度。
输入:
每个测试案例包含两行,第一行表示小木条的总个数(最多64根小木条),第二行表示每个小木条的长度,用空格分开。当第一行输入为零的时候表示程序结束。
输出:
对于每个测试案例输出最短的木棍长度。
解题思路:
用搜索算法去解决问题需要知道搜索的区间和剪枝条件,现在木棍长度未知,木棍个数未知,对于我们搜索是不利的。需要从已知条件推导到一个可以搜索的区间,然后再仔细思考如何剪枝来减少时间复杂度。
小木条是从木棍上砍下来的 => 木棍长度的下限:最长的小木条长度(part_max)
小木条的个数和长度已知 => 木棍长度的上限:所有小木条长度之和(part_sum)
确定搜索区间:木棍长度(stick_len) ∈ [part_max, part_sum] 并且 stick_len ∈ 整数
确定了stick_len => 确定了木棍的个数(stick_num)
剪枝1:当确定一个stick_len时候,那么这个stick_len要能整除part_sum,否则不能组成整数stick_num
剪枝2:见AC代码分析
剪枝3:见AC代码分析
AC代码:
// 19472897 2017 - 01 - 02 12:45 : 00 Accepted 1455 15MS 1724K 2328 B C++ 潮州牛肉丸
#include <stdio.h>
#include <algorithm>
#include <functional> int n; // the number of parts
int part[]; // the parts at most 64
int visit[]; // mark the situation of already used parts
int part_sum = ; // 所有小木条的长度之和
int stick_num = ; // 木棍的个数
int stick_len = ; // 木棍的长度 void init()
{
part_sum = ;
stick_num = ;
memset(part, , sizeof(part));
memset(visit, , sizeof(visit));
} // count:已经拼接好的木棍数,len:正在拼接的木棍长度,index:上一次搜索下标位置
bool dfs(int count, int len, int index)
{
if (stick_num == count)
return true; for (int i = index + ; i < n; ++i)
{
if (true == visit[i])
continue;
if (len + part[i] == stick_len)
{
visit[i] = true;
if (true == dfs(count + , , -))
return true;
visit[i] = false;
return false;
}
else if (len + part[i] < stick_len)
{
visit[i] = true;
if (true == dfs(count, len + part[i], i))
return true;
visit[i] = false; /* 已知条件:
1、stick的长度(stick_num)和个数(stick_num)
2、dfs已经返回false
*/ /* 剪枝2:当dfs返回false,len等于0的时候,stick的长度不是题目的正确结果,
后面的搜索无意义,直接返回false。 根据原则:如果当前搜索用的stick长度是题目的正确结果,那么所有的part都一定要被用上。
然而拼接一根新stick的时候(即len的值为0,表示当前正在拼接一根新stick),选取
的第一根part无论如何都能被用上,只是后面的part去配合第一根part完成一根stick,
如果在用第一根part的时候,dfs任然返回false,表示这个part不能被用上拼接stick。
与原则相违背。
*/
if ( == len)
return false; /* 剪枝3:
当前状态:dfs返回false,说明part[i]这根木条在当前count,len状态不可用,
接下来搜索的part[i+1]如果与之前的part[i]长度相同也一定不可用,注意我们是把part按降序排序过的*/
while (i < n && part[i] == part[i + ])
++i;
}
}
return false;
} int main(void)
{
while (scanf("%d", &n) != EOF && != n)
{
init();
for (int i = ; i < n; ++i)
{
scanf("%d", &part[i]);
part_sum += part[i]; //记录所有小木条长度之和
} std::sort(part, part + n, std::greater<int>()); // 按照降序排序 // stick的可能长度区间:[最长的小木条长度,所有小木条长度之和]
for (stick_len = part[]; stick_len < part_sum; ++stick_len)
{
if ( == part_sum % stick_len) //剪枝1:木棍的长度一定要能整除所有小木条长度之和
{
stick_num = part_sum / stick_len; // 得到stick的个数
if (true == dfs(, , -))
break;
}
} printf("%d\n", stick_len);
}
return ;
}
hdu 1455 Sticks(dfs+剪枝)的更多相关文章
- HDU 1455 Sticks(经典剪枝)
Sticks Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Sub ...
- hdu 1145(Sticks) DFS剪枝
Sticks Problem Description George took sticks of the same length and cut them randomly until all par ...
- hdu 1455 Sticks
Sticks Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Statu ...
- poj 1011 :Sticks (dfs+剪枝)
题意:给出n根小棒的长度stick[i],已知这n根小棒原本由若干根长度相同的长木棒(原棒)分解而来.求出原棒的最小可能长度. 思路:dfs+剪枝.蛮经典的题目,重点在于dfs剪枝的设计.先说先具体的 ...
- poj1011 Sticks(dfs+剪枝)
Sticks Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 110416 Accepted: 25331 Descrip ...
- hdu - 1072(dfs剪枝或bfs)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1072 思路:深搜每一个节点,并且进行剪枝,记录每一步上一次的s1,s2:如果之前走过的时间小于这一次, ...
- POJ 1011 - Sticks DFS+剪枝
POJ 1011 - Sticks 题意: 一把等长的木段被随机砍成 n 条小木条 已知他们各自的长度,问原来这些木段可能的最小长度是多少 分析: 1. 该长度必能被总长整除 ...
- HDU 1175 连连看 (DFS+剪枝)
<题目链接> 题目大意:在一个棋盘上给定一个起点和终点,判断这两点是否能通过连线连起来,规定这个连线不能穿过其它的棋子,并且连线转弯不能超过2次. 解题分析:就是DFS从起点开始搜索,只不 ...
- hdu 1044(bfs+dfs+剪枝)
Collect More Jewels Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Othe ...
随机推荐
- pip China
建个文件 ~/.pip/pip.conf, 内容如下 [global] index-url = http://b.pypi.python.org/simple [install] use-mirror ...
- delphi.指针.应用
注:初稿...有点乱,可能增删改... 因为指针应用,感觉不好写,请大家指出错误,谢谢. 注意: 本文着重点讲的是指针的各类型的应用或使用,而不是说这种方法不应该+不安全+危险+不提倡使用. 其它:本 ...
- Linux RPM、TAR包管理
一.RPM软件包命令的使用 RPM主要有5种基本操作模式:安装.卸载.刷新.升级及查询.下面分别介绍. 1.安装软件包 命令语法: rpm -ivh [RPM包文件名称] 命令中各参数的含义如下: - ...
- msChart组件安装与编程
首先下载mschart.ocx文件,至于它所依赖的.net环境,网上有很多,本人下载的插件给出链接,http://www.cr173.com/soft/47300.html而它所依赖的环境可以从我的云 ...
- oracle 查询执行过的SQL语句
SELECT * FROM v$sqlarea t WHERE t.FIRST_LOAD_TIME between '2016-12-23/16:03:00' and '2016-12-23/16:0 ...
- PHP命名空间的作用、为什么使用命名空间?
命名空间一个最明确的目的就是解决重名问题,PHP中不允许两个函数或者类出现相同的名字,否则会产生一个致命的错误.这种情况下只要避免命名重复就可以解决,最常见的一种做法是约定一个前缀. 举个栗子:项目中 ...
- MFC 自绘按钮 消息响应
单检测到按下消息时,发送一个消息 m_pParent->PostMessage(WM_COMMAND, IDC_BUTTON1); 然后再在消息映射里建立映射. ON_COMMAND(IDC_B ...
- Winform Textbox MultiLine和WordWrap属性的使用
突然用到,有些不明白,零乱记录下: 1.MultiLine属性为True时,Dock属性Fill值才能达到所需效果 2.MultiLine属性为False时,WordWrap属性也是无效果的,同1,T ...
- Linux 文件与目录管理
Linux 文件与目录管理 我们知道Linux的目录结构为树状结构,最顶级的目录为根目录 /. 其他目录通过挂载可以将它们添加到树中,通过解除挂载可以移除它们. 在开始本教程前我们需要先知道什么是绝对 ...
- Session操作
存储API localStorage和sessionStorage通常被当做普通的JavaScript对象使用:通过设置属性来存储字符串值,查询该属性来读取该值.除此之外,这两个对象还提供了更加正式的 ...