zoukankan      html  css  js  c++  java
  • USACO 6.3 Fence Rails(一道纯剪枝应用)

    Fence Rails
    Burch, Kolstad, and Schrijvers

    Farmer John is trying to erect a fence around part of his field. He has decided on the shape of the fence and has even already installed the posts, but he's having a problem with the rails. The local lumber store has dropped off boards of varying lengths; Farmer John must create as many of the rails he needs from the supplied boards.

    Of course, Farmer John can cut the boards, so a 9 foot board can be cut into a 5 foot rail and a 4 foot rail (or three 3 foot rails, etc.). Farmer John has an `ideal saw', so ignore the `kerf' (distance lost during sawing); presume that perfect cuts can be made.

    The lengths required for the rails might or might not include duplicates (e.g., a three foot rail and also another three foot rail might both be required). There is no need to manufacture more rails (or more of any kind of rail) than called for the list of required rails.

    PROGRAM NAME: fence8

    INPUT FORMAT

    Line 1: N (1 <= N <= 50), the number of boards
    Line 2..N+1: N lines, each containing a single integer that represents the length of one supplied board
    Line N+2: R (1 <= R <= 1023), the number of rails
    Line N+3..N+R+1: R lines, each containing a single integer (1 <= ri <= 128) that represents the length of a single required fence rail

    SAMPLE INPUT (file fence8.in)

    4
    30
    40
    50
    25
    10
    15
    16
    17
    18
    19
    20
    21
    25
    24
    30
    

    OUTPUT FORMAT

    A single integer on a line that is the total number of fence rails that can be cut from the supplied boards. Of course, it might not be possible to cut all the possible rails from the given boards.

    SAMPLE OUTPUT (file fence8.out)

    7
    

    HINTS (use them carefully!)

           HINT 1   

    This is a high dimensionality multiple knapsack problem, so we just have to test the cases. Given that the search space has a high out-degree, we will use depth first search with iterative deepening in order to limit the depth of the tree. However, straight DFSID will be too slow, so some tree-pruning is necessary.

    ————————————————————题解

    题解给了四个优化

    1、某两个要砍出的木板同长,我们就总在木料的非降序中砍它们

    2、有两个木料是同长的,我们总是去砍第一个

    3、一个木板和木料同长,那么一定要这么砍【这个优化很迷,没有加上】

    4、如果一个木料砍完后的长度小于最小的木板长,这个木料的剩余部分直接丢掉

    还有个优化是二分答案求最优解,所有点0.000

    一开始写的是针对每个背包往里面塞东西……应该是针对每个木板去看能不能割出来

    USACO总能让人关注到一些基础算法中你啥也不会的东西……这是最有趣的……也是最痛苦的……因为发现最后真是啥也不会……

     1 /*
     2 ID: ivorysi
     3 LANG: C++
     4 PROG: fence8
     5 */
     6 #include <iostream>
     7 #include <cstdio>
     8 #include <cstring>
     9 #include <queue>
    10 #include <set>
    11 #include <vector>
    12 #include <algorithm>
    13 #define siji(i,x,y) for(int i=(x);i<=(y);++i)
    14 #define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
    15 #define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
    16 #define sigongzi(j,x,y) for(int j=(x);j>(y);--j)
    17 #define inf 0x5f5f5f5f
    18 #define ivorysi
    19 #define mo 97797977
    20 #define hash 974711
    21 #define base 47
    22 #define fi first
    23 #define se second
    24 #define pii pair<int,int>
    25 #define esp 1e-8
    26 typedef long long ll;
    27 using namespace std;
    28 int n,r;
    29 int bag[55],sp;
    30 int wood[1505],sum[1505],mid,now;
    31 bool used[1505];
    32 void init() {
    33     scanf("%d",&n);
    34     siji(i,1,n) {
    35         scanf("%d",&bag[i]);
    36         sp+=bag[i];
    37     }
    38     sort(bag+1,bag+n+1);
    39     scanf("%d",&r);
    40     siji(i,1,r) {
    41         scanf("%d",&wood[i]);
    42     }
    43     sort(wood+1,wood+r+1);
    44     siji(i,1,r) {
    45         sum[i]=sum[i-1]+wood[i];
    46     }
    47 }
    48 bool dfs(int k,int pred) {
    49     if(k<=0) return 1;
    50     if(sp<sum[k]) return 0;
    51     sp-=wood[k];
    52     for(int i= k<mid&&wood[k]==wood[k+1] ?pred:1 ;i<=n;++i) {
    53         //有两个相同长度的木板需要切,让它们以一种非降序的顺序切出来
    54         if(bag[i]==bag[i-1]) continue;//这个木料和前一个一样,那么切之后会搜出来一个一模一样的结果
    55         if(bag[i]>=wood[k]) {
    56             bag[i]-=wood[k];
    57             if(bag[i]<wood[1]) sp-=bag[i];//这个木料不能切除任何一块木板了
    58             if(dfs(k-1,i)) {
    59                 if(bag[i]<wood[1]) sp+=bag[i];
    60                 sp+=wood[k];
    61                 bag[i]+=wood[k];
    62                 return 1;
    63             }
    64             if(bag[i]<wood[1]) sp+=bag[i];
    65             bag[i]+=wood[k];
    66         }
    67     }
    68     sp+=wood[k];
    69     return 0;
    70 }
    71 int binary() {
    72     int left=0,right=r;
    73     while(left<right) {
    74         mid=(left+right+1)>>1;
    75         if(sum[mid]>sp || wood[mid]>bag[n]) {right=mid-1;continue;} 
    76         if(dfs(mid,0)) left=mid;
    77         else right=mid-1;
    78     }
    79     return left;
    80 }
    81 void solve() {
    82     init();
    83     printf("%d
    ",binary());
    84 }
    85 int main(int argc, char const *argv[])
    86 {
    87 #ifdef ivorysi
    88     freopen("fence8.in","r",stdin);
    89     freopen("fence8.out","w",stdout);
    90 #else
    91     freopen("f1.in","r",stdin);
    92 #endif
    93     solve();
    94     return 0;
    95 }
  • 相关阅读:
    NET 4.+ & .NET CORE 高性能 轻量级 ORM框架,众多.NET框架中最容易使用的数据库访问技术
    mvc cookie
    正则表达式捕获带有属性的标签
    IT第十天
    代码段
    关于java.lang中String类的学习:最特殊的数据类型(持续整理中......)
    关于String.concat()方法和StringBuffer.append()方法的学习:方法是如何追加字符到源字符串的
    关于String和StringBuffer的理解问题:指针、变量的声明、变量的值的变化
    关于字符串检索、关键词的搜索问题:已搜索过的部分不会再被纳入下次搜索的范围内
    IT第九天
  • 原文地址:https://www.cnblogs.com/ivorysi/p/6682683.html
Copyright © 2011-2022 走看看