木棒

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. 安装idea开发工具

    1.网上去下载一个安装包,有的是需要注册码的(可以网上搜索注册码) 2.设置快捷键,可以直接选择使用eclipse的快捷键 3.配置maven 4.配置Git 5.配置tomcat

  2. android APK更新

    菜鸟的博客请多多指教 最近做了一个新功能,更新APK的功能 1.更新APK是一个耗时的任务,我采用了一个服务来做,上次在网上看到服务是在主线程里面,自己也测试了下,数据是真的 所以下载动作还必须在服务 ...

  3. 错误: java.lang.reflect.InvocationTargetException

    错误: java.lang.reflect.InvocationTargetException    at sun.reflect.NativeMethodAccessorImpl.invoke0(N ...

  4. 从mixin到new和prototype:Javascript原型机制详解

    从mixin到new和prototype:Javascript原型机制详解   这是一篇markdown格式的文章,更好的阅读体验请访问我的github,移动端请访问我的博客 继承是为了实现方法的复用 ...

  5. 360浏览器兼容模式默认显示ie最高版本

    之前写完代码都会放在360浏览器里跑一边,基本没啥问题,因为设置的都是极速模式,极速模式内置的是webkit内核,后来测试人员测试了兼容模式,发现会出各种问题,打开控制台一看,“我的天呐”,默认的竟然 ...

  6. 做App还是微信公众号,你该如何抉择?

    我不够聪明,因为我经常出于好奇被自己提出的问题所困扰,于是乎就有些强迫症似的拼命去寻求答案——我只是想说服自己,让自己从困扰的谜团中清醒.坚定方向,进而能从容不迫的走下去... 最近在考虑一个问题:做 ...

  7. idea初使用之配置使用maven仓库

    idea使用的理由已经无需多说.现在已经超过了eclipse.java开发种占有44%.第一次使用上手还是挺难的.跟用惯了myeclipse的我来说.对于project的概念深入人心.还理解不了它的M ...

  8. Lex&Yacc Parser错误发生后再次parser之前恢复初始状态

    使用lex yacc 对文件进行parser时,如果文件内容有错,parser报错,然后你修改了文件,再次读入文件进行parser,如果你不是重启程序进行parser,那就需要对做些处理了. &quo ...

  9. 如何在脚本中获取进程ID(PID)

    我想要知道运行中脚本子shell的进程id.我该如何在shell脚本中得到PID. 当我在执行shell脚本时,它会启动一个叫子shell的进程.作为主shell的子进程,子shell将shell脚本 ...

  10. 【 2013 Multi-University Training Contest 8 】

    HDU 4678 Mine 对于每个空白区域,求SG值. 最后异或起来等于0,先手必败. #pragma comment(linker,"/STACK:102400000,102400000 ...