poj1011 Sticks DFS+回溯

转载请注明出处:http://blog.csdn.net/u012860063

题目链接:http://poj.org/problem?id=1011

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 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

Source

Central Europe 1995

题目的大意:是给了你有限个棍子以及每个棍子的长度,而且所有的棍子都是由有限个长度相同的棍子截断得到的,让你求被截棍子的最小长度,本题的算法是深搜,当然需要几个剪枝的!

代码如下:

#include <iostream>
#include <algorithm>
using namespace std;
int sticks[65];
int used[65];
int n,len;
bool dfs(int i,int l,int t)//i为当前试取的棍子序号,l为要拼成一根完整的棍子还需要的长度,t初值为所有棍子总长度
{
    if(l==0)
    {
        t -= len;//如果len为所有棍子的和
        if(t == 0)
			return true;
        for(i = 0; used[i]; i++);            //剪枝1:搜索下一根大棍子的时候,找到第一个还没有使用的小棍子开始
		used[i]=1;                           //由于排序过,找到的第一根肯定最长,也肯定要使用,所以从下一根开始搜索
        if(dfs(i+1,len-sticks[i],t))
			return true;
        used[i]=0;//回溯
        t+=len;
    }
    else
    {
        for(int j = i; j < n; j++)
        {
            if(j>0 && (sticks[j]==sticks[j-1]&&!used[j-1]))  //剪枝2:前后两根长度相等时,如果前面那根没被使用,也就是由前面那根
                continue;                                                //开始搜索不到正确结果,那么再从这根开始也肯定搜索不出正确结果,此剪枝威力较大
            if(!used[j] && l>=sticks[j])   //剪枝3:最简单的剪枝,要拼成一根大棍子还需要的长度L>=当前小棍子长度,才能选用
            {
                l-=sticks[j];
                used[j]=1;
                if(dfs(j,l,t))
					return true;
                l+=sticks[j];//回溯
                used[j]=0;
                if(sticks[j]==l)    //剪枝4:威力巨大的剪枝,程序要运行到此处说明往下的搜索失败,若本次的小棍长度刚好填满剩下长度,但是后
                    break;           //面的搜索失败,则应该返回上一层
            }
        }
    }
    return false;
}
bool cmp(const int a, const int b)
{
    return a>b;
}
int main()
{
    while(cin>>n&&n)
    {
        int sum=0;int max = -1;
        for(int i = 0; i < n; i++)
        {
            cin>>sticks[i];
            sum += sticks[i];
            used[i] = 0;
			if(sticks[i] > max)//找出最长的棍子
				max = sticks[i];
        }

        sort(sticks,sticks+n,cmp);   //剪枝5:从大到小排序后可大大减少递归次数

        bool flag=false;
        for(len = max; len <= sum/2; len++)   //剪枝6:大棍长度一定是所有小棍长度之和的因数,且最小因数应该不小于小棍中最长的长度
        {
            if(sum%len == 0)
            {
                if(dfs(0,len,sum))
                {
                    flag=true;
                    cout<<len<<endl;
                    break;
                }
            }
        }
        if(!flag)
            cout<<sum<<endl;
    }
    return 0;
}

poj1011 Sticks DFS+回溯

时间: 2024-10-01 02:45:26

poj1011 Sticks DFS+回溯的相关文章

POJ1011 Sticks DFS+剪枝

Description 乔治拿来一组等长的木棒,将它们随机地砍断,使得每一节木棍的长度都不超过50个长度单位.然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度.请你设计一个程序,帮助乔治计算木棒的可能最小长度.每一节木棍的长度都用大于零的整数表示. Input 输入包含多组数据,每组数据包括两行.第一行是一个不超过64的整数,表示砍断之后共有多少节木棍.第二行是截断以后,所得到的各节木棍的长度.在最后一组数据之后,是一个零. Output 为每组数据,分别输出

EOJ1981 || POJ1011 经典dfs+剪枝+奇怪的数据

题目:EOJ1981 || POJ1011   经典dfs+剪枝+奇怪的数据 Description George took sticks of the same length and cut them randomly until all partsbecame at most 50 units long. Now he wants to return sticks to the originalstate, but he forgot how many sticks he had origi

Sticks(回溯和剪枝和关于局部变量的问题)

做这道题要哭了= = 之前把所有的变量都定义成全局变量,结果提交时老是RT,找不到错.后来改成局部变量就ac了= =. Sticks(3.4.2) Time Limit:1000MS    Memory Limit:10000KB    64bit IO Format:%I64d & %I64u SubmitStatus Description George took sticks of the same length and cut them randomly until all parts

CodeForces 550B Preparing Olympiad(DFS回溯)

[题目链接]:click here~~ [题目大意] 一组题目的数目(n<=15),每个题目有相应的难度,问你选择一定的题目(大于r个且小于l个)且选择后的题目里最小难度与最大难度差不小于x,求选择方案数. [解题思路]: DFS+回溯. 先发一发比较拙的代码: #include <bits/stdc++.h> using namespace std; const int N=1e5+10; int num[N],mum[N]; int n,m,q,t,l,r; int top,ans,

HDU4499 Cannon DFS 回溯的应用

题意就是给你一个n*m的棋盘,然后上面已经有了 棋子,并给出这些棋子的坐标,但是这些棋子是死的就是不能动,然后让你在棋盘上面摆炮,但是炮之间不能互相吃,吃的规则我们斗懂得 炮隔山打嘛,问你最多能放几个炮 肯定是搜索了,n,m最大才5,可能挺久没做了,对于回溯反而把握不好了,写了好久调试了好久,才过 #include <stdio.h> #include <iostream> #include <algorithm> #include <string.h> #

POJ2488-A Knight&#39;s Journey(DFS+回溯)

题目链接:http://poj.org/problem?id=2488 A Knight's Journey Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 36695   Accepted: 12462 Description Background The knight is getting bored of seeing the same black and white squares again and again

蓝桥杯 算法提高 8皇后&#183;改 -- DFS 回溯

  算法提高 8皇后·改   时间限制:1.0s   内存限制:256.0MB 问题描述 规则同8皇后问题,但是棋盘上每格都有一个数字,要求八皇后所在格子数字之和最大. 输入格式 一个8*8的棋盘. 输出格式 所能得到的最大数字和 样例输入 1 2 3 4 5 6 7 89 10 11 12 13 14 15 1617 18 19 20 21 22 23 2425 26 27 28 29 30 31 3233 34 35 36 37 38 39 4041 42 43 44 45 46 47 48

poj1321——dfs回溯

POJ 1321  DFS回溯+递归枚举 棋盘问题 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 24813   Accepted: 12261 Description 在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别.要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C. Input 输入含有多组测试数据. 每组数据的第一行

hduoj2553——N皇后问题,dfs回溯

hduoj 2553  dfs,回溯 N皇后问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 10297    Accepted Submission(s): 4634 Problem Description 在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的