题目大意:

  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+剪枝)的更多相关文章

  1. HDU 1455 Sticks(经典剪枝)

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

  2. hdu 1145(Sticks) DFS剪枝

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

  3. hdu 1455 Sticks

    Sticks Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Statu ...

  4. poj 1011 :Sticks (dfs+剪枝)

    题意:给出n根小棒的长度stick[i],已知这n根小棒原本由若干根长度相同的长木棒(原棒)分解而来.求出原棒的最小可能长度. 思路:dfs+剪枝.蛮经典的题目,重点在于dfs剪枝的设计.先说先具体的 ...

  5. poj1011 Sticks(dfs+剪枝)

    Sticks Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 110416   Accepted: 25331 Descrip ...

  6. hdu - 1072(dfs剪枝或bfs)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1072 思路:深搜每一个节点,并且进行剪枝,记录每一步上一次的s1,s2:如果之前走过的时间小于这一次, ...

  7. POJ 1011 - Sticks DFS+剪枝

    POJ 1011 - Sticks 题意:    一把等长的木段被随机砍成 n 条小木条    已知他们各自的长度,问原来这些木段可能的最小长度是多少 分析:    1. 该长度必能被总长整除    ...

  8. HDU 1175 连连看 (DFS+剪枝)

    <题目链接> 题目大意:在一个棋盘上给定一个起点和终点,判断这两点是否能通过连线连起来,规定这个连线不能穿过其它的棋子,并且连线转弯不能超过2次. 解题分析:就是DFS从起点开始搜索,只不 ...

  9. hdu 1044(bfs+dfs+剪枝)

    Collect More Jewels Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Othe ...

随机推荐

  1. 来自 Thoughtram 的 Angular 2 系列资料

    Angular 2 已经正式 Release 了,Thoughtram 已经发布了一系列的文档,对 Angular 2 的各个方面进行深入的阐释和说明. 我计划逐渐将这个系列翻译出来,以便对大家学习 ...

  2. Linux内核模块设计

    内核的设计有两种方式:单内核和微内核,两者各有优劣,关于两者的比较可以参见wiki.windowds和Solaris采用微内核结构. Linux内核采用单内核结构,设计比较简单,但单内核的理念是把所有 ...

  3. Access restriction错误解决办法

    Access restriction错误, XX方法 is not accessible due to restriction on required library XXlib 解决方案: Ecli ...

  4. how to enable remote access for root user

    GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'password' WITH GRANT OPTION;

  5. tomcat出现的PermGen Space问题

    java.lang.OutOfmemoryError: PermGen Space 的错误,导致项目无法正常运行. 出现这个错误的原因,总结一下: PermGen Space指的是内存的永久保存区,该 ...

  6. nodejs——qureystring的作用

    当node服务器向另一个服务器发送数据时,首先要转换成字符串再post或者get,这个时候就要用到node内置的这个包querystring, querystring.stringify(data);

  7. 针对APP的测试过程和重点关注内容,做以下梳理和总结

    转载自金阳光测试:http://blog.sina.com.cn/s/blog_12df1b9e60102vy57.html   1. 首先是测试资源确认及准备 (1)产品需求文档.产品原型图.接口说 ...

  8. VS2013配置WTL91_5321_Final

    网上关于WTL的文章,尤其是中文的文章不多,根据收集的资料整理出了VS2013安装WTL的方法. .下载.文件很小的,地址:http://sourceforge.net/projects/wtl/fi ...

  9. oracle驱动问题

    转载   http://sosuny.iteye.com/blog/806390

  10. css之z-index

    要想z-index可以使用,就要配合定位元素使用即position 如果定位元素z-index没有发生嵌套: 1.后来居上的准则 2.哪个大,哪个上 例如 如果定位元素z-index发生嵌套: 1.祖 ...