zoukankan      html  css  js  c++  java
  • 【bzoj1082】栅栏[SCOI2005]

    显然我们取的肯定是前ans块木板。然后砍的木材也应该是从小到大砍(如果小的木材可以满足条件,就一定不会去动大的木材)

    所以两遍排序。

    二分答案。

    然后对于要取的每块木板,我们搜索它是在第x块木板上砍下来的。。

    要加剪枝:

    ①如果砍下了这块木材然后这块木材小于第一块木板,那就失去价值,用t来记录。当t>tot-s[now],(tot是记录的所有给的木板长度),那么退出。

    ②如果b[now]==b[now-1]那么从当前点开始枚举就可以了,因为前面小的点都被跳过了

     

    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    using namespace std;
     
    #define N 60
    #define M 1010
     
    int n,m;
    int tot,mid;
    int t;
     
    int a[N],b[M],c[N];
    int s[M];
     
    bool DFS(int now,int d)
    {
        if (!now)
            return true;
        if (t>tot-s[mid])
            return false;
        for (int i=d;i<=m;i++)
            if (c[i]>=b[now])
            {
                c[i]-=b[now];
                if (c[i]<b[1])
                    t+=c[i];
                if (b[now]==b[now-1])
                {
                    if (DFS(now-1,i))
                        return true;
                }
                else
                {
                    if (DFS(now-1,1))
                        return true;
                }
                if (c[i]<b[1])
                    t-=c[i];
                c[i]+=b[now];
            }
        return false;
    }
     
    int work(int mid)
    {
        for (int i=1;i<=m;i++)
            c[i]=a[i];
        t=0;
        return DFS(mid,1);
    }
     
    int main()
    {
        scanf("%d",&m);
        for (int i=1;i<=m;i++)
            scanf("%d",&a[i]),tot+=a[i];
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
            scanf("%d",&b[i]);
        sort(a+1,a+m+1);
        sort(b+1,b+n+1);
        for (int i=1;i<=n;i++)
            s[i]=s[i-1]+b[i];
        while (s[n]>tot)
            n--;
        int l=0,r=n;
        while (l<r)
        {
            mid=(l+r)>>1;
            if (work(mid+1))
                l=mid+1;
            else
                r=mid;
        }
        printf("%d
    ",l);
        return 0;
    }
    

      

  • 相关阅读:
    最小的k个数
    复杂链表的复制
    二叉树中和为某一值的路径
    二叉搜索树的后序遍历序列
    STL之Deque容器
    STL之迭代器
    STL之Vector容器
    STL之string
    STL(标准模板库)基本概念
    文件I/O
  • 原文地址:https://www.cnblogs.com/yangjiyuan/p/5320956.html
Copyright © 2011-2022 走看看