George took sticks of the same length and cut them randomly until all parts became at most 50 units long. Now he wants to return sticks to the original state, but he forgot how many sticks he had originally and how long they were originally. Please help him and design a program which computes the smallest possible original length of those sticks. All lengths expressed in units are integers greater than zero. 

Input

The input contains blocks of 2 lines. The first line contains the number of sticks parts after cutting, there are at most 64 sticks. The second line contains the lengths of those parts separated by the space. The last line of the file contains zero.

Output

The output should contains the smallest possible length of original sticks, one per line. 

Sample Input

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

Sample Output

6
5 题意 
给出一定数量的小木棒的长度,它是由等长的若干木棒随意砍断所得到的。对于给定的一组小木棒,请求出原始木棒的最小长度。
题解
dfs搜索,
思想很简单,一个接一个的把木棍拼起来,最后把木棍用光。关键的地方是几个剪枝技巧:设所有木棍的总长度为 Sum, 最终的答案(长度)是 L。
1. 首先要明白, Sum一定要能被 L 整除。
2. L 一定 大于等于 题目给出的最长的木棍的长度 Max。由上述两点,我们想到,可以从 Max 开始递增地枚举 L, 直到成功地拼出 Sum/L 支长度为 L 的木棍。
搜索中的剪枝技巧:
3. 将输入的输入从大到小排序,这么做是因为一支长度为 K 的完整木棍,总比几支短的小木棍拼成的要好。形象一些:如果我要拼 2 支长为8的木棍,第一支木棍我拼成 5 + 3 然后拼第二支木棍但是失败了,而我手中还有长为 2 和 1 的木棍,我可以用 5 + 2 + 1 拼好第一支,再尝试拼第二支,仔细想一想,就会发现这样做没意义,注定要失败的。我们应该留下 2+1 因为 2+1 比 3 更灵活。
4. 相同长度的木棍不要搜索多次, 比如:我手中有一些木棍, 其中有 2 根长为 4 的木棍, 当前搜索状态是 5+4+.... (即表示长度为 5,4,2 的三支拼在一起, ...表示深层的即将搜索的部分), 进行深搜后不成功,故我没必要用另一个 4 在进行 5+4+...5. 将开始搜索一支长为 L 的木棍时,我们总是以当前最长的未被使用的 木棍开始,如果搜索不成功,那么以比它短的开始那么也一定不能取得全局的成功。因为每一支题目给出的木棍都要被用到。如果,有4 5 4 4 3 2想拼成长为 6 的木棍,那么从 5 开始, 但是显然没有能与 5一起拼成 6 的,那么我就没必要去尝试从 4 开始的,因为最终 5 一定会被遗弃。在拼第 2 3 ... 支木棍时,一样。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<sstream>
#include<cmath>
#include<cstdlib>
#include<queue>
using namespace std;
#define PI 3.14159265358979323846264338327950 int len[];
bool vis[];
int sum,l,n; int cmp(const void *a,const void *b)
{
return *(int *)b-*(int *)a;
} bool dfs(int m,int left)
{
if(m== && left==)
return true;
if(left==)
left=l;
for(int i=;i<n;++i)
{
if(!vis[i] && len[i]<=left)
{
if(i>)
{
if(!vis[i-] && len[i]==len[i-])
continue;
}
vis[i]=true;
if(dfs(m-,left-len[i]))
return true;
else
{
vis[i]=false;
if(left==len[i]||left==l)   //重要剪枝,不佳这句会超时
return false;
}
}
}
return false;
} int main()
{
while(scanf("%d",&n) && n)
{
sum=;
for(int i=;i<n;i++)
{
scanf("%d",&len[i]);
sum=sum+len[i];
}
qsort(len,n,sizeof(int),cmp);
for(l=len[];l<=sum/;++l)
{
if(sum % l)
continue;
memset(vis,false,sizeof(vis));
if(dfs(n,l))
{
printf("%d\n",l);
break;
} }
if(l>sum/)
printf("%d\n",sum);
}
}

poj-1011 sticks(搜索题)的更多相关文章

  1. POJ 1011 sticks 搜索

    Sticks Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 125918   Accepted: 29372 Descrip ...

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

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

  3. DFS(剪枝) POJ 1011 Sticks

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

  4. POJ 1011 - Sticks DFS+剪枝

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

  5. POJ 1011 Sticks(搜索 && 剪枝 && 经典)

    题意 : 有n根木棍(n<=64),它们由一些相同长度的木棍切割而来,给定这n根木棍的长度,求使得原来长度可能的最小值. 分析 : 很经典的深搜题目,我们发现答案只可能是所有木棍长度总和的因数, ...

  6. POJ 1011 Sticks(dfs+剪枝)

    http://poj.org/problem?id=1011 题意:若干个相同长度的棍子被剪成若干长度的小棍,求每根棍子原来的可能最小长度. 思路:很经典的搜索题. 我一开始各种超时,这题需要很多剪枝 ...

  7. OpenJudge 2817:木棒 / Poj 1011 Sticks

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

  8. POJ 1011 Sticks 【DFS 剪枝】

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

  9. poj 1011 Sticks ,剪枝神题

    木棒 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 118943 Accepted: 27429 Description 乔治拿 ...

  10. poj 1011 Sticks (DFS+剪枝)

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

随机推荐

  1. HDU 1029 一道微软面试题

    http://acm.hdu.edu.cn/showproblem.php?pid=1029 给定一个数组,其中有一个相同的数字是出现了大于等于(n + 1) / 2次的.要求找出来. 1.明显排序后 ...

  2. 渣渣菜鸡的 ElasticSearch 源码解析 —— 环境搭建

    关注我 转载请务必注明原创地址为:http://www.54tianzhisheng.cn/2018/08/25/es-code01/ 软件环境 1.Intellij Idea:2018.2版本 2. ...

  3. 洛谷P1057 传球游戏

    f[i][j]表示第i轮j拿到球的方案数 转移:f[i][j]=f[i-1][j+1] +f[i-1][j+-1].注意: 边界f[0][1]=1; 还有当j=1或N时 #include<ios ...

  4. linq动态分页排序

    if (!string.IsNullOrEmpty(order) && !string.IsNullOrEmpty(dir))//判断排序的字段名称和排序的类型是否为空 { if (d ...

  5. 什么是JavaScript

    来源:https://www.koofun.com/pro/kfpostsdetail?kfpostsid=30&cid= JavaScript是一种松散类型的客户端脚本语言,在用户浏览器中执 ...

  6. ubuntu 14.04 安装minidwep-gtk

    一,安装相关的依赖 sudo apt-get install build-essential libssl-dev iw libpcap-dev sqlite3 libsqlite3-dev libp ...

  7. 总结一下WindowListener的用法

    记录一下便于自己查看 1.WindowListener java.awt.event 接口 WindowListener public interface WindowListener extends ...

  8. If people in the communications only think about gains and losses of interest, then the pleasure of knowing each other will cease to exist.

    If people in the communications only think about gains and losses of interest, then the pleasure of ...

  9. Linux下常用的数据恢复工具

    一.数据删除 命令:rm -rf,将任何数据直接从硬盘删除,且没有任何提示 建议做法: 把命令参数放到后面:rm -rfi 将删除的东西通过mv命令移动到系统下的/temp目录下,然后写个脚 本定期执 ...

  10. 两个有序数列,求中间值 Median of Two Sorted Arrays

    原题: There are two sorted arrays nums1 and nums2 of size m and n respectively.Find the median of the ...