hdu 1455 Sticks(经典深搜+剪枝)

简介:

Sticks

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3582    Accepted Submission(s): 903


Problem Description
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 file 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
这是以前做过的题poj(1011),当时从网上看了好久,虽然过了,可是隔了这么久了,发现还是有必要再写一遍
这次AC的就容易多了,和以前写的差不多,这次用了一个结构体存储木棒信息,但是所有的剪枝还是没有少,这里是剪枝的经典运用,一定要学好了。。。。
干巴爹。。。
复制代码
#include <iostream>
#include <algorithm>
using namespace std;

//total能组成的木棒的组数,l:组成的木棒的长度
int total,l;
//num:输入的整数,sum:总长度
int num,sum;
typedef struct
{
    int length;//木棒的长度
    bool mark;//木棒是否被使用过
}Sticks;
Sticks sticks[70];

bool cmp(Sticks a,Sticks b)
{
    return a.length>b.length;
}
//s 已组成的木棒数目,len已经组成的长度,pos搜索的木棒的下标的位置
int dfs(int s,int len,int pos)
{
    if(s==total)return 1;
    for(int i=pos+1;i<num;i++)
    {
        //如果这个木棒已经用过,则继续下一根
        if(sticks[i].mark)continue;
        if(len+sticks[i].length == l)
        {
            sticks[i].mark = true;
            if(dfs(s+1,0,-1))return true;
            sticks[i].mark = false;
            return false;
        }else if(sticks[i].length+len<l){
            sticks[i].mark = true;
            if(dfs(s,len+sticks[i].length,i))
            return true;
            sticks[i].mark = false;
            //剪枝:如果当前搜索时,前边的长度为0,而第一根没有成功的使用,
            //说明第一根始终要被废弃,所以这种组合必定不会成功
            //此处的剪枝必须有,因为这里的剪枝会节省很多的无用搜索,
            //我试了一下,此处剪枝省去就会超时的。。。。
            if(len==0)return false;
            //剪枝:如果当前和上一次搜到的木棒是一样长的则没必要再搜一次了
            while(sticks[i].length==sticks[i+1].length)i++;
        }
    }
    return false;
}

int main()
{

    while(cin>>num&&num!=0)
    {
        sum = 0;//标记为0
        for(int i = 0; i < num; i++)
        {
            cin>>sticks[i].length;
            sum += sticks[i].length;
            sticks[i].mark = false;
        }
        //将木棒按照长度从长到短的顺序排序
        sort(sticks,sticks+num,cmp);
        //从木棒的最长的那根开始搜索,因为最小的组合也会大于等于最长的那根
        for(l = sticks[0].length; l <= sum; l++)
        {
            //剪枝一:如果不能被整除说明不能组成整数根木棒,搜下一个
            if(sum%l!=0)continue;
            total = sum / l;//得到木棒总数目
            if(dfs(1,0,-1))
            {
                cout<<l<<endl;
                break;
            }
        }
    }
    return 0;
}
复制代码

 










本文转自NewPanderKing51CTO博客,原文链接:http://www.cnblogs.com/newpanderking/archive/2012/10/08/2715413.html ,如需转载请自行联系原作者


相关文章
|
存储
poj 3254 Corn Fields (状态压缩dp)
状态压缩dp其实就是用二进制来表示所有的状态,比如这题, 我们在某一行可以这样取0 1 0 1 1 0 1,用1代表取了,0代表没取,因为这点,它的数据量也限制在20以内,所有看到这样数据量的题目可以先考虑一下状态压缩dp。对于有多行的数据,所有状态的总数必然很庞大,而且不用特殊的方法想要存储这些状态是不太现实的。既然每个点只有这两种情况,我们可以用二进制的一位来表示,0 1 0 1 1 0 1就可以表示为二进制0101101也就是十进制的45,如果我们想要枚举6个点的所有状态,我们只需要从0到2^6取其二进制就可以了,并不会重复或是多余。
29 0
|
5月前
【洛谷 P1219】[USACO1.5]八皇后 Checker Challenge 题解(深度优先搜索+回溯法)
**USACO1.5八皇后挑战**是关于在$n\times n$棋盘上放置棋子的,确保每行、每列及两条主对角线上各有一个且仅有一个棋子。给定$6$作为输入,输出前$3$个解及解的总数。例如,对于$6\times6$棋盘,正确输出应包括解的序列和总数。代码使用DFS解决,通过跟踪对角线占用状态避免冲突。当找到所有解时,显示前三个并计数。样例输入$6$产生输出为解的前三个排列和总数$4$。
35 0
|
机器学习/深度学习 算法 程序员
【算法合集】深搜广搜Prim与Kruskal
广度优先搜索(BFS)又叫广搜,它像一个有远见的人,它是一层一层来实现搜索的,也挺像下楼梯的。 思路: 1.先初始化队列 q; 2.从起点开始访问,并且改变他的状态为已经访问; 3.如果他的队列非空,取出首个元素,将它弹出! 4.如果u == 目标状态,然后对所以与 u 邻近的点进入队列; 5.标记它已经被访问!...............
169 1
【算法合集】深搜广搜Prim与Kruskal
AtCoder Beginner Contest 216 G - 01Sequence (并查集 贪心 树状数组 差分约束)
AtCoder Beginner Contest 216 G - 01Sequence (并查集 贪心 树状数组 差分约束)
151 0
【HDU】1175 连连看(BFS + 剪枝)
【HDU】1175 连连看(BFS + 剪枝)
257 0
【HDU】1175 连连看(BFS + 剪枝)
|
Go
[Nowcoder / POJ2728] 最优比率生成树 | 二分 + prim
有n个点,其中,每个点给出位置坐标( x , y ) 以及高度z ,两点之间的距离为两点之间的欧几里得距离 两点之间建立一条路的代价为两点之间的高度差,问将n 个点联通的情况下,求出最大的cost/dis
127 0
|
C语言
HDOJ/HDU Tempter of the Bone(深搜+奇偶性剪枝)
HDOJ/HDU Tempter of the Bone(深搜+奇偶性剪枝)
97 0
Sticks(剪枝+BFS)
Problem Description George took sticks of the same length and cut them randomly until all parts became at most 50 units long.
1411 0
|
算法 数据建模 消息中间件
单源最短路SPFA算法
$huaji^{233……}$模板:洛谷 P3371 #include #include #include #include #include using namespace std; struct data{ int v;int next; int valu...
1156 0