为了这题还去学了下迭代加深 回来还是不会写

只好参考各大神的代码及题解了

二分枚举最大可以切的块数 然后就是各种分析及优化

USACO题解里写了7个优化。。

问题分析

抽象一下就可以发现,算法的本质是多重背包问题。 补充:这题与破锣乐队都是多个背包,不可重复放物品。区别在于破锣乐队要有顺序,此题不需要,这样此题就必须要搜索才行。 单个背包的问题我们可以用DP解决,但是对于这种问题我们只能用搜索了。 但是可以看一看这道题的数据规模:1<=n<=50,1<=r<=1023。如此大的规模我们只能考虑进一步的优化。

我采用的是dfsid搜索每一个rail来源的board。以下技巧都是针对这种搜索顺序来制定的。 (注:rail是所需要切成的东西,board是供应商提供的原料)

如果使用dancing links的话,可以让程序的常数快2倍。

优化技巧

  1. 很容易就能注意到,由于每块rail的价值是相等的——也就是说切小的要比切大的来的划算。那么我们在搜索能否切出i个rail的方案是自然要选最小的i个rail来切。
  2. 经过一些实验可以发现,先切大的rail比先切小的rail更容易提前出解。同样,[先切小的board比先切大的board更容易提前出解?]{注:好像先切大的board要比先切小的更快}。{*我的程序先切小再切大第5个点就TLE了,而先切大再切小就快很多,见C++程序.{跟我一样,握个手,一定要先大后小!!!}}
  3. 由于r最大可能是1023,但是rail长度的范围却只有0~128,这点提醒了我们有很多rail的长度会是相同的。所以我们要避免冗余,优化搜索顺序。若有rail[i+1]=rail[i],则rail[i+1]对应的board一定大于等于rail[i]对应的board。可以通过这种方法剪掉很多冗余的枝条。
  4. 相应的,如果board[i]=board[i+1],那么从board[i]切下的最大的rail一定大于等于从board[i+1]切下的最大的rail。
  5. 对于切剩下的board(无法再切下rail),统计一下总和。如果这个值大于board长度的总和减去rail长度的总和,一定无解,可以剪枝。这个剪枝最关键。
  6. 二分答案
  7. 其实在读入的过程中,如果rail[i] > max{board} 那么这个rail应该舍去 By Clarkok
  8.  /*
    ID: shangca2
    LANG: C++
    TASK: fence8
    */
    #include <iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<stdlib.h>
    using namespace std;
    int bo[],te[],ra[],v;
    int n,m,res,s,sum[],flag;
    void dfs(int tt,int st)
    {
    int i;
    if(flag) return ;
    if(tt==)//全部可以切完
    {
    flag = ;
    return ;
    }
    int ss=,o;
    for(i = ; i <= n ; i++)//当前木板剩余值已经大于最多的剩余值 肯定不用再搜
    { if(te[i]<ra[])
    ss+=te[i];
    }
    if(ss>v) return ;
    for(i = st ; i <= n ; i++)
    {
    if(te[i]>=ra[tt])
    { if(tt->=&&ra[tt]==ra[tt-])//一个小优化 如果ra[tt]已经在i~N里搜了 那么前面跟它相等的 就不会在i之前搜了
    o = i;
    else
    o = ;
    te[i]-=ra[tt];
    dfs(tt-,o);
    te[i]+=ra[tt];
    }
    }
    return ;
    }
    int main()
    {
    //freopen("fence8.in","r",stdin);
    //freopen("fence8.out","w",stdout);
    int i;
    cin>>n;
    for(i = ; i <= n ; i++)
    {
    scanf("%d",&bo[i]);
    s+=bo[i];
    }
    sort(bo+,bo+n+);
    for(i = ; i <= n ; i++)
    te[i] = bo[i];
    scanf("%d",&m);
    for(i = ; i <= m ; i++)
    {
    scanf("%d",&ra[i]); }
    sort(ra+,ra+m+);
    for(i = ; i <= m ; i++)
    sum[i] = sum[i-]+ra[i];
    int low=,high = m;
    while(low<high)//二分找一下 满足最多可以切多少块
    {
    int mm = (low+high+)>>;
    v = s-sum[mm];
    flag = ;
    dfs(mm,);
    if(flag)
    low = mm;
    else
    high = mm-;
    }
    printf("%d\n",low);
    return ;
    }

usaco4.12Fence Rails(迭代加深)的更多相关文章

  1. POJ1129Channel Allocation[迭代加深搜索 四色定理]

    Channel Allocation Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 14601   Accepted: 74 ...

  2. BZOJ1085: [SCOI2005]骑士精神 [迭代加深搜索 IDA*]

    1085: [SCOI2005]骑士精神 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1800  Solved: 984[Submit][Statu ...

  3. 迭代加深搜索 POJ 1129 Channel Allocation

    POJ 1129 Channel Allocation Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 14191   Acc ...

  4. 迭代加深搜索 codevs 2541 幂运算

    codevs 2541 幂运算  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题目描述 Description 从m开始,我们只需要6次运算就可以计算出 ...

  5. HDU 1560 DNA sequence (IDA* 迭代加深 搜索)

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1560 BFS题解:http://www.cnblogs.com/crazyapple/p/321810 ...

  6. poj2286The Rotation Game(迭代加深dfs)

    链接 把迭代加深理解错了 自己写了半天也没写对 所谓迭代加深,就是在深度无上限的情况下,先预估一个深度(尽量小)进行搜索,如果没有找到解,再逐步放大深度搜索.这种方法虽然会导致重复的遍历 某些结点,但 ...

  7. IOI1994 北京2008的挂钟 迭代加深

    总的来讲,这是一道很⑨的题,因为: (1)题目中有⑨个挂钟 (2)有⑨种操作方案 (3)这题因为解空间太小所以可以直接⑨重循环!! 这题可以用迭代加深搜索高效求解,剪枝的策略也很显然: >所求的 ...

  8. 迭代加深搜索算法总结 + Editing a Book UVa11212题解

    迭代加深搜索算法: 对于可以用回溯法解决,但是解答树结点数大的恐怖的问题的一种解决办法,有的问题甚至用bfs连一层节点都遍历不完就超时了.具体方法就是依次枚举搜索层数,从1到一个上限. 结构: int ...

  9. codevs 2541 幂运算(迭代加深搜索)

    /* 一开始想到了简单的深搜 维护当前可用的mi数组 然后回溯用哪个 不断更新新产生的mi 这样的问题是 由于mi不断产生 搜索规模扩大 不好 不好 下面是奇丑的WA掉的代码 做个反面教材 */ #i ...

随机推荐

  1. windows server 2003 负载平衡的详细设置步骤(转载)

    声明:本文为转载. 当把一台服务器(包括Web服务器.FTP服务器或者流媒体服务器等等)放入网络中之后,随着客户端数量的不断增加,人们往往需要功能更强大.处理速度更快的服务器.为了解决这个问题,如果将 ...

  2. Mysql的联合查询

    联合查询 union联合查询 语法:     select 语句 union [all|distinct] select 语句; 示例: 特点:     条件:两表的查询出来的字段数目必须相同     ...

  3. [位运算] [搜索] [递推优化] [计算几何] TEST 2016.7.15

    NOIP2014 提高组模拟试题 第一试试题 题目概况: 中文题目名称 合理种植 排队 科技节 源程序文件名 plant.pas/.c/.cpp lineup.pas/.c/.cpp scifest. ...

  4. 九度OJ 1351 数组中只出现一次的数字

    题目地址:http://ac.jobdu.com/problem.php?pid=1351 题目描述: 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 输 ...

  5. 抽象工厂(Abstract Factory)模式

    一.抽象工厂(Abstract Factory)模式 抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态. 为了方便引进抽象工厂模式,引进一个新概念:产品族(Product Family ...

  6. Linux+svn无法显示日志

    自己在linux中配置了一个svn服务器,但是客户端在浏览日志的时候报错.提示不能连接到服务器,是否离线查看... 谷歌了一下,是因为svnserve.conf中配置了anon-access = re ...

  7. js实现克隆一个对象

    var app={}; app.cloneobj= function(obj){ var o; if(typeof obj == "object"){ if(obj===null) ...

  8. [HTML]img标签属性

    <img src="image.png" width="" height="" align="absmiddle" ...

  9. office 问题集

    ----20131012---------------------------------------------------------------------------------------- ...

  10. 【JPA】query新对象 需要 构造函数

    构造函数 @Query("select g from Note g where id=?1" ) Note findById(Long id); @Query("sele ...