zoukankan      html  css  js  c++  java
  • BZOJ1082: [SCOI2005]栅栏

    1082: [SCOI2005]栅栏

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 1906  Solved: 816
    [Submit][Status][Discuss]

    Description

      农夫约翰打算建立一个栅栏将他的牧场给围起来,因此他需要一些特定规格的木材。于是农夫约翰到木材店购
    买木材。可是木材店老板说他这里只剩下少部分大规格的木板了。不过约翰可以购买这些木板,然后切割成他所需
    要的规格。而且约翰有一把神奇的锯子,用它来锯木板,不会产生任何损失,也就是说长度为10的木板可以切成长
    度为8和2的两个木板。你的任务:给你约翰所需要的木板的规格,还有木材店老板能够给出的木材的规格,求约翰
    最多能够得到多少他所需要的木板。

    Input

      第一行为整数m(m<= 50)表示木材店老板可以提供多少块木材给约翰。紧跟着m行为老板提供的每一块木板的长
    度。接下来一行(即第m+2行)为整数n(n <= 1000),表示约翰需要多少木材。接下来n行表示他所需要的每一块木板
    的长度。木材的规格小于32767。(对于店老板提供的和约翰需要的每块木板,你只能使用一次)。

    Output

      只有一行,为约翰最多能够得到的符合条件的木板的个数。

    Sample Input

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

    Sample Output

    7

    HINT

    25切出 21 30切出 20 40切出 19、18 50切出 15、16、17

    Source

    题解:神奇的DFS+剪枝

       二分答案:我们先排序所有需要裁出来的木头,再二分答案!

       DFS:我们考虑每块木头由谁裁剪出来 时间复杂度:n^m

       剪枝:1.当出现答案时,不再回溯!

          2.当剩下的木材<需要裁的木材时!

          3.当当前木材大小等于前一个木材大小时,从它的最小匹配开始!【这个剪枝是最关键的】

       总结:反正这样就A了,而且跑的飞快,我一直认为剪枝这种东西过于玄幻,

          导致我这种弱菜根本不会分析时间复杂度,果然暴力出奇迹这句话是没错的!

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #define ll long long
    #define ld long double
    #define N 1005
    using namespace std;
    int n,m,sa,mid,ans;
    int a[N],b[N],sb[N],bl[N];
    bool bool_flag;
    int read()
    {
        int x=0,f=1; char ch;
        while (ch=getchar(),ch<'0'||ch>'9') if (ch=='-') f=-1;
        while (x=x*10+ch-'0',ch=getchar(),ch>='0'&&ch<='9');
        return x*f;
    }
    void dfs(int A,int B,int w)
    {
        if (B==0) {bool_flag=1; return;}
        while (A<=n && a[A]<b[1]) w+=a[A],A++;
        if (bool_flag || w+sb[mid]>sa || A>n) return;
        int t=A,t1=A,t2=B,t3=w;
        if (b[B]==b[B+1] && B!=mid) t=bl[B+1];
        for (int i=t; i<=n; i++)
        {
            if (a[i]>=b[B]){
                bl[B]=i; a[i]-=b[B]; B--; 
                dfs(A,B,w);
                A=t1; B=t2; w=t3; a[i]+=b[B]; 
            }
        }
    }
    int main()
    {
        n=read(); for (int i=1; i<=n; i++) a[i]=read();
        m=read(); for (int i=1; i<=m; i++) b[i]=read();
        sort(a+1,a+n+1); sort(b+1,b+m+1);
        while (b[m]>a[n]) m--; int tot=0;
        for (int i=1; i<=n; i++) if (a[i]>b[1]) a[++tot]=a[i];
        n=tot;
        for (int i=1; i<=n; i++) sa+=a[i];
        sb[0]=0; for (int i=1; i<=m; i++) sb[i]=sb[i-1]+b[i];
        int l=1,r=m;
    //    cout<<" "<<n<<" "<<m<<endl;
        while (l<=r)
        {
            mid=(l+r)>>1; bool_flag=0; dfs(1,mid,0);
            if (bool_flag) ans=mid,l=mid+1; else r=mid-1;
        }
        printf("%d
    ",ans);
        return 0;
    }
    /*
    4
    30
    40
    50
    25
    10
    20
    20
    20
    20
    20
    20
    20
    20
    20
    20
    
    */
  • 相关阅读:
    C#中怎么设置comboBox1为只读,即不可在里面进行编辑?
    笔记
    Head First ObjectOriented Analysis & Design 读书 概记
    看到这篇东西 ,要收藏 呵呵
    HELLO OPENGL
    调试opengl程序出错
    HeadFirst C# 读书笔记 0426
    css布局容易范的一些错误
    百度新年贪吃蛇效果
    css3教程:boxsizing属性说明
  • 原文地址:https://www.cnblogs.com/HQHQ/p/6036458.html
Copyright © 2011-2022 走看看