UVA-307 Sticks (DFS+剪枝)

题目大意:用n根长度未必相等的木棒匹配出最多数量的等长木棒。

题目分析:枚举所有可能的等长木棒的长度,通过DFS的方式逐根匹配,在此过程中要剪枝。先将木棒长度按从大到小排序,也就是说匹配每一根等长木棒时总是优先挑选长的。剪枝方案如下:1. 若第i-1根木棒在当前方案的匹配中没有用到并且length[i]==length[i-1],则第i根木棒也不可能用到;2.若已匹配成功cnt根等长木棒,而第cnt+1根匹配不成功,则要剪枝;3.若在匹配第cnt+1根木棒时,最长的那根木棒stick会第一个被选择,若此时第cnt+1根等长木棒匹配失败,则第cnt+1根等长木棒无须继续匹配,返回第cnt根等长木棒的匹配即可,因为与stick在此次匹配时匹配的可选木棒范围要比以后更大,此次都匹配不成,以后更匹配不成,要重新匹配第cnt根木棒,得以产生新的最长木棒stick’,再由此尝试匹配第cnt+1根等长木棒。

以上三条缺一不可!!!

代码如下:

# include<iostream>
# include<cstdio>
# include<vector>
# include<cstring>
# include<algorithm>
using namespace std;

int w[100],n,vis[100];

bool myComp(const int &a,const int &b)
{
    return a>b;
}

bool dfs(int cur,int g,int id,int cnt,int sum)
{
    if(g*cnt==sum)
        return true;

    for(int i=id;i<n;++i){
        if(vis[i])
            continue;
        if(i&&!vis[i-1]&&w[i-1]==w[i])///剪枝1
            continue;
        if(cur+w[i]==g){
            vis[i]=1;
            if(dfs(0,g,0,cnt+1,sum))
                return true;
            vis[i]=0;
            return false;///剪枝2
        }
        else if(cur+w[i]<g){
            vis[i]=1;
            if(dfs(cur+w[i],g,i+1,cnt,sum))
                return true;
            vis[i]=0;
            if(cur==0)
                return false;///剪枝3
        }
    }
    return false;
}

int main()
{
    int sum;
    while(~scanf("%d",&n)&&n)
    {
        sum=0;
        for(int i=0;i<n;++i){
            scanf("%d",w+i);
            sum+=w[i];
        }

        sort(w,w+n,myComp);

        int flag=0;
        for(int g=w[0];g<=sum/2;++g){
            if(sum%g==0){
                memset(vis,0,sizeof(vis));
                if(dfs(0,g,0,1,sum)){
                    flag=1;
                    printf("%d\n",g);
                    break;
                }
            }
        }
        if(!flag)
            printf("%d\n",sum);
    }
    return 0;
}

  

时间: 2024-10-14 22:08:01

UVA-307 Sticks (DFS+剪枝)的相关文章

uva 307 Sticks(回溯剪枝)

uva 307 Sticks 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 origi

[POJ 1011]Sticks(DFS剪枝)

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 original

POJ 1011 - Sticks DFS+剪枝

POJ 1011 - Sticks 题意:    一把等长的木段被随机砍成 n 条小木条    已知他们各自的长度,问原来这些木段可能的最小长度是多少 分析:    1. 该长度必能被总长整除    2. 从大到小枚举,因为小长度更灵活, 可拼接可不拼接    3. 因为每一跟木条都要用到, 故若轮到其中一根原始木段选它的第一根木条时,若第一根木条若不满足,则显然第一根木条在接下来任何一根原始木段都不会满足,故无解    4. 由于所有棒子已排序,在DFS时,若某根棒子未被选,则跳过其后面所有与

UVa307 Sticks (DFS+剪枝)

链接:http://vjudge.net/problem/19648 分析:这题重要的是剪枝.maxd表示的是最小可能长度(把砍完的木棍长度降序排好,最小可能长度大于等于砍完后最长的木棍长度,小于等于总长度的一半,且木棍的根数是整数,所以(总长度%每段最小可能长度=0)),dfs的三个状态分别为cur表示当前要凑maxd长度的木棍已经凑好的长度,from表示从砍完后的第from根木棍开始考虑,cnt表示已经凑好maxd长度木棍的根数. 1.将所有木棍按长度从大到小排序,dfs组合木棍时优先使用长

POJ1011 Sticks DFS+剪枝

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

POJ 1011 Sticks dfs,剪枝 难度:2

http://poj.org/problem?id=1011 要把所给的集合分成几个集合,每个集合相加之和ans相等,且ans最小,因为这个和ans只在[1,64*50]内,所以可以用dfs一试 首先ans需要满足两个条件1.可以被总集合的和sum整除 2.是总集合的某个子集的和 对于条件1,可以通过试除遍历 对于条件2,可以通过dp预筛选,这两个花费时间都不大 接着搜索能不能划分成集合之和恰为ans的若干集合, 1. 可以从大向小找,因为大的更不灵活,而且所有的元素都需要取到 2.比如对于5,

DFS + 剪枝策略

一:简介 (1)相信做过ACM的人,都很熟悉图和树的深度优先搜索:算法里面有蛮力法 -- 就是暴力搜索(不加任何剪枝的搜索): (2)蛮力搜搜需要优化时,就是需要不停的剪枝,提前减少不必要的搜索路径,提前发现判断的过滤条件: (3)剪枝的核心问题就是设计剪枝判断方法,哪些搜索路径应当舍弃,哪些搜索路径不能舍弃(保留): (4)高效的剪枝过滤条件需要从局部和全局来考虑问题,发现内在的规律. (5)详细的剪枝算法,请见剪枝算法(算法优化) 二:示例验证 (1)题目来源于 poj 1011 Stick

UVA 10318 - Security Panel dfs 剪枝

UVA 10318 - Security Panel dfs 剪枝 ACM 题目地址:UVA 10318 - Security Panel 题意: 这题跟点灯的题目很像,点灯游戏选择一盏灯时会让它以及四周的灯改变状态. 但是我们有特殊的开开关技巧,它给出了改变状态的位置,而不是四周都改变. 问你从全部关着变成全部开着的最小开关步骤. 分析: 很明显,在一个位置上点两次或更多次是没有必要的,所以一个位置只有选择与不选择,用dfs即可,但如果暴力所有可能,复杂度是2^25,会超时,所以要剪枝. 由于

POJ - 1011 - Sticks (DFS + 剪枝)

题目传送:Sticks 思路:DFS + 剪枝 AC代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <vector> #include <map> #include

uva 219 - Department of Redundancy Department(dfs+剪枝)

题目链接:uva 219 - Department of Redundancy Department 题目大意:给定一些关系,问哪一些关系是可以被替代的,如果可以被替代,给出替代的方案,一种即可. 解题思路:因为总共也就26个字母,所以用二进制数表示状态.剪枝,每次将所有可选关系均考虑进去都无法满足则是false. #include <cstdio> #include <cstring> #include <algorithm> using namespace std;