当前位置: 首页 > news >正文

poj 1011 Sticks ,剪枝神题

木棒
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 118943 Accepted: 27429
Description
乔治拿来一组等长的木棒。将它们随机地砍断。使得每一节木棍的长度都不超过50个长度单位。然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度。请你设计一个程序,帮助乔治计算木棒的可能最小长度。每一节木棍的长度都用大于零的整数表示。
Input
输入包括多组数据,每组数据包括两行。

第一行是一个不超过64的整数,表示砍断之后共同拥有多少节木棍。第二行是截断以后。所得到的各节木棍的长度。在最后一组数据之后,是一个零。


Output
为每组数据,分别输出原始木棒的可能最小长度,每组数据占一行。
Sample Input
9
5 2 1 5 2 1 5 2 1
4
1 2 3 4
0
Sample Output
6

5


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

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

int sticks[100];
bool used[100];
int n, StickLen, len;

bool dfs(int i,int l,int t)
//i为当前试取的棍子序号,l为要拼成一根完整的棍子还须要的长度,t初值为全部棍子总长度
{
    if(l==0) {
        t-=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;
}
int main()
{
    int i, totalLen;
    bool flag;
    while(scanf("%d",&n),n) {
        totalLen = 0;
        for(i=0; i<n; ++i) {
            scanf("%d",&sticks[i]);
            totalLen += sticks[i];
        }
        sort(sticks, sticks+n, cmp);
        memset(used, 0, sizeof used );
        flag = false;
        for(StickLen = sticks[0]; StickLen <=totalLen/2; ++StickLen) {
            len = StickLen;
            if(totalLen % StickLen == 0)
                if(dfs(0, StickLen, totalLen) ) {
                    flag= true;
                    printf("%d\n",StickLen);
                    break;
                }
        }
        if(!flag) {
            printf("%d\n",totalLen);
        }
    }
    return 0;
}


相关文章:

  • 删除缓存
  • java 深拷贝
  • 为什么可以用while(cin)?
  • linux centos 6.5 安装L2TP *** 每账号绑定1IP地址
  • 解决: Fail to create empty document
  • div,section,article的区别以及使用场景
  • Oracle高水位High Water Mark(HWM)简介
  • Android中使用adb访问SQLite的方法
  • 集群安装配置Hadoop具体图解
  • Nodejs·理解Buffer
  • Commit message 和 Change log 编写指南
  • 瓜娃系列 (4) - Resources和Files
  • mysqlhelper
  • 开发APP不搞清楚这20个问题,必然沦为一场灾难
  • YII 实现布局
  • IE9 : DOM Exception: INVALID_CHARACTER_ERR (5)
  • [Vue CLI 3] 配置解析之 css.extract
  • ABAP的include关键字,Java的import, C的include和C4C ABSL 的import比较
  • CSS相对定位
  • css选择器
  • ECMAScript6(0):ES6简明参考手册
  • express如何解决request entity too large问题
  • github从入门到放弃(1)
  • PAT A1092
  • vue的全局变量和全局拦截请求器
  • 测试开发系类之接口自动化测试
  • 从重复到重用
  • 搭建gitbook 和 访问权限认证
  • 前端存储 - localStorage
  • 前端面试之闭包
  • 浅谈JavaScript的面向对象和它的封装、继承、多态
  • 小程序、APP Store 需要的 SSL 证书是个什么东西?
  • 写给高年级小学生看的《Bash 指南》
  • 学习ES6 变量的解构赋值
  • 一个项目push到多个远程Git仓库
  • - 转 Ext2.0 form使用实例
  • 你对linux中grep命令知道多少?
  • PostgreSQL 快速给指定表每个字段创建索引 - 1
  • 积累各种好的链接
  • ​2020 年大前端技术趋势解读
  • ## 临床数据 两两比较 加显著性boxplot加显著性
  • #ifdef 的技巧用法
  • (2)关于RabbitMq 的 Topic Exchange 主题交换机
  • (bean配置类的注解开发)学习Spring的第十三天
  • (笔试题)分解质因式
  • (二)windows配置JDK环境
  • (终章)[图像识别]13.OpenCV案例 自定义训练集分类器物体检测
  • (转)Windows2003安全设置/维护
  • .NET 6 Mysql Canal (CDC 增量同步,捕获变更数据) 案例版
  • .NET Core WebAPI中使用Log4net 日志级别分类并记录到数据库
  • .NET CORE使用Redis分布式锁续命(续期)问题
  • .NET6使用MiniExcel根据数据源横向导出头部标题及数据
  • .Net的C#语言取月份数值对应的MonthName值
  • .NET基础篇——反射的奥妙
  • .NET连接MongoDB数据库实例教程