木棒

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 136132   Accepted: 32036

Description

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

Input

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

Output

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

Sample Input

9
5 2 1 5 2 1 5 2 1
4
1 2 3 4
0

Sample Output

6
5

Source

 
方法:DFS+强剪枝
分析:经典的搜索问题,需要细细考虑剪枝条件,每一次的剪枝都能大幅度提升速度。
剪枝:
1. 首先将数据从大到小排序,搜索的时候从大到小搜索,这样才能保证数据的充分使用,而且对剪枝也很有帮助
2. 原始每根木条的长度是总长度的约数,所以搜索空间是总长度的约数
3. 检索的时候,用最长木条的长度作为搜索的起始长度
4. 如果stick[i] == stick[i+1],且stick[i]匹配失败,那么stick[i+1]必然也是失败的
5. 如果第i组的第一根木条(也是最长的)在匹配过程中失败,那么就直接返回第i-1组重新匹配。因为第i组的组合一定是最长木条的子集。
 
 #include <stdio.h>
#include <stdlib.h>
#include <string.h> #define MAX_NUM 64
#define FAILURE 1
#define SUCCESS 0 int gwStickNum = ;
int gwtotalLen;
int gwData[MAX_NUM];
int gwSelect[MAX_NUM];
int gwGroup; void sort(int *a, int left, int right)
{
if(left >= right)
{
return;
}
int i = left;
int j = right;
int key = a[left];
while(i < j)
{
while(i<j && key>=a[j])
{
j--;
}
a[i] = a[j];
while(i<j && key<=a[i])
{
i++;
}
a[j] = a[i];
}
a[i] = key;
sort(a, left, i-);
sort(a, i+, right);
} int match(int goal, int sum, int nowGroup)
{
int i = ;
if(sum > goal) return FAILURE;
if(sum == goal)
{
nowGroup++;
if(nowGroup == gwGroup) return SUCCESS;
sum = ;
return match(goal, sum, nowGroup);
}
for(i=; i<gwStickNum; i++)
{
if(gwSelect[i] == ) continue;
sum += gwData[i];
gwSelect[i] = ;
if(SUCCESS == match(goal, sum, nowGroup)) return SUCCESS;
gwSelect[i] = ;
sum -= gwData[i];
if(sum == ) return FAILURE;
while(gwData[i] == gwData[i+] && i < gwStickNum)
{
i++;
}
}
return FAILURE;
} int searchFactors(int start)
{
int i = ;
for(i=start+; i<=gwtotalLen; i++)
{
if(gwtotalLen % i ==) return i;
}
return ;
} int calc()
{
int sum = gwData[];
int Len = ;
gwSelect[] = ;
int start = gwData[]-;
while(start < gwtotalLen)
{
Len = searchFactors(start);
gwGroup = gwtotalLen / Len;
if(SUCCESS == match(Len, sum, )) return Len;
start = Len;
memset(gwSelect, , sizeof(gwSelect));
gwSelect[] = ;
sum = gwData[];
}
return ;
} int getTatolLen(int *a, int arryLen)
{
int i = ;
int sum = ;
for(i=; i<arryLen; i++)
{
sum += a[i];
}
return sum;
} int main(void)
{
int i = ;
int result = ;
while(scanf("%d", &gwStickNum), gwStickNum != )
{
for(i=; i<gwStickNum; i++)
{
scanf("%d", &gwData[i]);
} gwtotalLen = getTatolLen(gwData, gwStickNum);
sort(gwData, , gwStickNum-);
result = calc(); printf("%d\n", result);
memset(gwSelect, , sizeof(gwSelect));
} return ;
}
测试数据:
9
15 3 2 8 8 4 11 8 1
0 20
------------------------------------------------------
27
15 3 2 4 11 1 8 8 8 15 3 2 4 11 1 8 8 8 15 3 2 4 11 1 8 8 8
0 20
------------------------------------------------------
9
5 2 1 5 2 1 5 2 1
4
1 2 3 4
0 6
5
------------------------------------------------------
46
40 37 32 10 47 4 42 56 61 23 59 36 27 16 16 37 26 19 14 29 31 58 51 32 63 28 11 25 12 15 39 42 46 43 11 19 53 17 39 21 45 44 8 23 51 55
58
57 6 44 4 16 35 54 9 32 23 43 55 46 41 8 41 55 44 31 59 57 58 59 29 53 30 3 39 52 17 32 45 8 40 34 18 20 11 32 33 14 41 31 25 4 42 54 9 29 37 47 29 34 20 47 56 61 5
26
3 64 18 49 4 40 18 61 50 36 17 49 8 17 62 11 24 8 36 59 34 26 28 7 37 26
0 89
89
99

北大poj-1011的更多相关文章

  1. 北大POJ题库使用指南

    原文地址:北大POJ题库使用指南 北大ACM题分类主流算法: 1.搜索 //回溯 2.DP(动态规划)//记忆化搜索 3.贪心 4.图论 //最短路径.最小生成树.网络流 5.数论 //组合数学(排列 ...

  2. DFS(剪枝) POJ 1011 Sticks

    题目传送门 /* 题意:若干小木棍,是由多条相同长度的长木棍分割而成,问最小的原来长木棍的长度: DFS剪枝:剪枝搜索的好题!TLE好几次,终于剪枝完全! 剪枝主要在4和5:4 相同长度的木棍不再搜索 ...

  3. OpenJudge 2817:木棒 / Poj 1011 Sticks

    1.链接地址: http://bailian.openjudge.cn/practice/2817/ http://poj.org/problem?id=1011 2.题目: 总时间限制: 1000m ...

  4. POJ 1011 - Sticks DFS+剪枝

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

  5. 搜索+剪枝——POJ 1011 Sticks

    搜索+剪枝--POJ 1011 Sticks 博客分类: 算法 非常经典的搜索题目,第一次做还是暑假集训的时候,前天又把它翻了出来 本来是想找点手感的,不想在原先思路的基础上,竟把它做出来了而且还是0 ...

  6. POJ 1011 Sticks 【DFS 剪枝】

    题目链接:http://poj.org/problem?id=1011 Sticks Time Limit: 1000MS   Memory Limit: 10000K Total Submissio ...

  7. poj 1011

    http://poj.org/problem?id=1011 这是一道POJ的搜索的题目,最开始确实难以理解,但做过一些搜索的题目后,也没那么难了. 大概题意就是,现在有N根木头,要拼成若干根木头,并 ...

  8. POJ 1011 Sticks dfs,剪枝 难度:2

    http://poj.org/problem?id=1011 要把所给的集合分成几个集合,每个集合相加之和ans相等,且ans最小,因为这个和ans只在[1,64*50]内,所以可以用dfs一试 首先 ...

  9. poj 1011 搜索减枝

    题目链接:http://poj.org/problem?id=1011 #include<cstdio> #include<cstring> #include<algor ...

  10. poj 1011 Sticks (DFS+剪枝)

    Sticks Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 127771   Accepted: 29926 Descrip ...

随机推荐

  1. 用python爬取QQ空间

    好久没写博文了,最近捣鼓了一下python,好像有点上瘾了,感觉python比js厉害好多,但是接触不久,只看了<[大家网]Python基础教程(第2版)[www.TopSage.com]> ...

  2. XUtils3 的 环境搭建

    XUtils3 的 环境搭建 环境搭建三部曲 ----------------------- 说明 : author  修雨轩陈 使用andorid Studio 已经创建了一个项目 并且自己需要使用 ...

  3. Python’s SQLAlchemy vs Other ORMs[转发 4]peewee

    peewee peewee is a small, expressive ORM. Compared to other ORMs, peewee focuses on the principal of ...

  4. 利用mysql_multi来管理多实例:

    mysql_multi的现实意义: 1:随着连接数上升,性能会下降,通过多实例来分流大量连接来提高性能. 2:做资源隔离 3:分库分表 mysql_multi是官方管理多实例的一个脚本,利用perl语 ...

  5. JS学习笔记--轮播图效果

    希望通过自己的学习收获哪怕收获一点点,进步一点点都是值得的,加油吧!!! 本章知识点:index this for if else 下边我分享下通过老师教的方式写的轮播图,基础知识实现: 1.css代 ...

  6. Windows下安装pip(转自http://www.cnblogs.com/yuanzm/p/4089856.html)

    windows下面安装Python和pip终极教程 在大二的时候接触过一段时间的Python,最近又开始玩起了这门语言.总的来说,个人很喜欢Python的语言风格,但是这门语言对于windows并不算 ...

  7. IOS跳转到设置特定项

    App如何跳转到系统Settings 标签: IOS开发App转到Settings 2015-12-04 15:56 550人阅读 评论(1) 收藏 举报  分类: IOS开发(21)  版权声明:本 ...

  8. css3圆角(还有百分比设置椭圆) 阴影 字体

    一. 现在前面只写知识点,全部内容放在后面截图展示: 给元素添加圆角: border-radius属性,他的值如果等于高的一半,将会等到一个圆形,大于一半叶然是一个圆形 radius是指半径,他求出圆 ...

  9. hello 漂亮的小靓仔

    <form type="text" name="超级" method="post"> <table align=" ...

  10. 杭电1597--find the nth digit--假设:S1 = 1,S1=12,S3=123,S4=1234...

    我是把它分层来求的,也就是说第一层是1,第二层是12,第三层是123......你们该懂的!! #include <iostream>#include <cmath>using ...