题意:给出n根小棒的长度stick[i],已知这n根小棒原本由若干根长度相同的长木棒(原棒)分解而来。求出原棒的最小可能长度。

思路:dfs+剪枝。蛮经典的题目,重点在于dfs剪枝的设计。先说先具体的实现:求出总长度sum和小棒最长的长度max,则原棒可能的长度必在max~sum之间,然后从小到大枚举max~sum之间能被sum整除的长度len,用dfs求出所有的小棒能否拼凑成这个长度,如果可以,第一个len就是答案。

下面就是关键的了,就是这道题dfs的实现和剪枝的设计:

1.以一个小棒为开头,用dfs看看能否把这个小棒拼凑成len长,如果可以,用vis[i]记录下用过的小棒,然后继续以另外一个小棒为开头,以此类推。

2.小棒的长度从大到小排序,这个就不解释了。

3.如果当前最长的小棒不能拼成len长,那么就返回前一步,更改前一步的最长小棒的组合情况(这里不能是全部退出),不用再继续搜索下去了。

4.最重要的,就是比如说17,9,9,9,9,8,8,5,2……如果当前最长小棒为17,它与第一个9组合之后dfs发现不能拼成len,那么17就不用和后面所有的9组合了,而直接和8开始组合。这个剪枝直接从TLE到16MS,很强大。

源代码:(160K 16MS)

#include<iostream>
#include<algorithm>
using namespace std;
const int Max = 65;

int n, len, stick[Max];
bool flag, vis[Max];

bool cmp(int a, int b){
    return a> b;
}

void dfs(int dep, int now_len, int u){   // dep为当前已被用过的小棒数,u为当前要处理的小棒。
    if(flag) return;
    if(now_len == 0){                    //  当前长度为0,寻找下一个当前最长小棒。
        int k = 0;
        while(vis[k]) k ++;              //  寻找第一个当前最长小棒。
        vis[k] = true;
        dfs(dep + 1, stick[k], k + 1);
        vis[k] = false;
        return;
    }
    if(now_len == len){                  //  当前长度为len,即又拼凑成了一根原棒。
        if(dep == n) flag = true;        //  完成的标志:所有的n根小棒都有拼到了。
        else dfs(dep, 0, 0);
        return;
    }
    for(int i = u; i < n; i ++)
        if(!vis[i] && now_len + stick[i]< = len){
            if(!vis[i-1] && stick[i] == stick[i-1]) continue;      //  不重复搜索:最重要的剪枝。
            vis[i] = true;
            dfs(dep + 1, now_len + stick[i], i + 1);
            vis[i] = false;
        }
}

int main(){
    while(scanf("%d", &n)&& n != 0){
        int sum = 0;
        flag = false;
        for(int i = 0; i < n; i ++){
            scanf("%d", &stick[i]);
            sum += stick[i];
        }
        sort(stick, stick + n, cmp);     //  从大到小排序。
        for(len = stick[0]; len < sum; len ++)
            if(sum % len == 0){          //  枚举能被sum整除的长度。
                memset(vis, 0, sizeof(vis));
                dfs(0, 0, 0);
                if(flag) break;
            }
        printf("%d\n", len);
    }
    return 0;
}

poj 1011 :Sticks (dfs+剪枝)的更多相关文章

  1. POJ 1011 - Sticks DFS+剪枝

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

  2. POJ 1011 Sticks dfs,剪枝 难度:2

    http://poj.org/problem?id=1011 要把所给的集合分成几个集合,每个集合相加之和ans相等,且ans最小,因为这个和ans只在[1,64*50]内,所以可以用dfs一试 首先 ...

  3. poj 1011 Sticks ,剪枝神题

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

  4. DFS(剪枝) POJ 1011 Sticks

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

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

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

  6. poj 1011 Sticks (DFS+剪枝)

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

  7. POJ 1011 Sticks 【DFS 剪枝】

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

  8. OpenJudge 2817:木棒 / Poj 1011 Sticks

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

  9. uva 215 hdu 1455 uvalive5522 poj 1011 sticks

    //这题又折腾了两天 心好累 //poj.hdu数据极弱,找虐请上uvalive 题意:给出n个数,将其分为任意份,每份里的数字和为同一个值.求每份里数字和可能的最小值. 解法:dfs+剪枝 1.按降 ...

随机推荐

  1. 【BZOJ2793】[Poi2012]Vouchers 调和级数

    [BZOJ2793][Poi2012]Vouchers Description 考虑正整数集合,现在有n组人依次来取数,假设第i组来了x人,他们每个取的数一定是x的倍数,并且是还剩下的最小的x个.正整 ...

  2. 《从零开始学Swift》学习笔记(Day 45)——重写方法

    原创文章,欢迎转载.转载请注明:关东升的博客 重写实例方法 在子类中重写从父类继承来的实例方法和静态方法.先介绍实例方法的重写. 下面看一个示例: class Person { var name: S ...

  3. java拾遗5----Java操作Mongo入门

    Java操作Mongo入门 参考: http://api.mongodb.com/java/3.2/ http://www.runoob.com/mongodb/mongodb-java.html h ...

  4. bfs_迷宫求最短路径

    宽度优先搜索按照距离开始状态由近及远的顺序进行搜索,可以很容易用来求解最短路径或者最少操作等问题. 将已经访问过的状态用标记管理起来,便可以很好地做到由近及远的搜索. import java.util ...

  5. Oracle 12c 读书笔记(二):Oracle数据库体系结构

    以11g来分析 数据库实例包括:SGA和一系列后台管理.监控简称 数据库包括三种文件:数据文件.控制文件.重做日志文件 数据库实例和数据库是Orale数据库体系的核心部分 Oracle服务器和实例 实 ...

  6. 安装nginx包

    1.二进制安装源码包,直接输入yum stall nginx -y就可以 2,后面会涉及路径,所以先查下nginx的路径rpm -ql nginx 3,进入bin目录进行设置 4, 5,查看系统自带的 ...

  7. Linux中的位置参数变量

    解释: 主要是向脚本中传递数据,变量名不能自定义,变量作用是固定的 $n $0代表命令本身,$1-9代表接受的第1-9个参数,10以上需要用{}括起来,比如${10}代表接收的第10个参数 $* 代表 ...

  8. POJ 1470 Closest Common Ancestors【近期公共祖先LCA】

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u013912596/article/details/35311489 题目链接:http://poj ...

  9. opencv3计算机视觉+Python(四)

    使用分水岭和GrabCut算法进行物体分割 用GrabCut算法进行图像分割 在OpenCV中,实现了grabcut分割算法,该算法可以方便的分割出前景图像,操作简单,而且分割的效果很好.算法的原理参 ...

  10. RedisClient For .Net

    Redis Client For .Net 介绍 redis支持各种语言版本的client,其中.net平台下比较火的有ServiceStack.Redis和StackExchange.Redis 选 ...