• USACO 4.1.2 栅栏的木料


    这个讲的超好....一定要看...然后看我代码就好懂啦...

    http://blog.csdn.net/ta201314/article/details/41287567

    各种优化确实非常好....搜索的一道好题...

    挂代码:

    /*
        Problem : USACO 4.1.2 栅栏的木料
        Author : Robert Yuan
        
        优化解释:
        0. 二分+贪心判断可行解 (根据自己设计的贪心算法尽量的得到一个比较靠近正确值的 ans,再后面的搜索的下界就会大大提高)
        1. 如果使用的木料与上一块的木料大小相同,那么上一块若没有选前 i块木板,这一块也不要选(1.若是因为前面的太小而不选,那么对于这个也太小  2.若是因为前面的情况已经搜过,那我选择前面的就成了一个已经搜索过的情况)
        2. 如果当前需要枚举的木板与上一块木板的大小相同,只选其中最后的那块,理由同上。
        3. 如果剩下的木板大小比第一块还小,那么就是属于余料,将所有余料和已经切好的木料减去,剩下的木板长度如果比未切好的 x个木料总长还要小,那么这种状态也是不可行的 
    */
    
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    
    inline int in(){
        int x=0;char ch=getchar();
        while(ch>'9' || ch<'0') ch=getchar();
        while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
        return x;
    }
    
    const int maxn=52;
    const int maxm=1025;
    const int INF=0x7f7f7f7f;
    
    int n,m,S,ans;
    int tmp[maxn];
    int a[maxn],b[maxm],s[maxm];
    
    bool cmp(const int &a,const int &b){
        return a>b;
    }
    
    bool dfs(int x,int last){
        if(!x) return true;
        if(S<s[x]) return false;/*优化 3*/
        S-=b[x];
        for(int i= x!=ans && b[x]==b[x+1] ? last:1/*优化 1*/;i<=n;i++){
            while(i<n && a[i]==a[i+1]) i++;/*优化 2*/
            if(a[i]>=b[x]){
                a[i]-=b[x];
                if(a[i]<b[1]) S-=a[i];
                if(dfs(x-1,i)){
                    if(a[i]<b[1]) S+=a[i];
                    a[i]+=b[x];    S+=b[x];
                    return true;
                }
                if(a[i]<b[1]) S+=a[i];
                a[i]+=b[x];
            }
        }
        S+=b[x];
        return false;
    }
    
    bool check(int m){/*优化 0*/
        int Minn,Minx;
        memcpy(tmp,a,sizeof(a));
        for(int i=m;i;i--){
            Minn=INF,Minx=-1;
            for(int j=1;j<=n;j++)
                if(tmp[j]>=b[i] && Minn>tmp[j])
                    Minn=tmp[j],Minx=j;
            if(Minx<0) return false;
            tmp[Minx]-=b[i];
        }
        return true;
    }
    
    
    int main(){    
        n=in();
        for(int i=1;i<=n;i++) a[i]=in(),S+=a[i];
        m=in();
        for(int i=1;i<=m;i++) b[i]=in();
        
        sort(a+1,a+n+1);
        sort(b+1,b+m+1);
        
        for(int i=1;i<=m;i++)
            s[i]=s[i-1]+b[i];
        
        int l=0,r=m,mid;
        
        if(check(r)){
            printf("%d",m);return 0;
        }
        
        while(l+1<r){
            mid=(l+r)>>1;
            if(check(mid)) l=mid;
            else r=mid;
        }
        ans=r;
        while(dfs(ans,1) && ans<=m) ans++;
        printf("%d",ans-1);
        
        return 0;
    }
    View Code
  • 相关阅读:
    《构建之法》4、17章精读
    2016012005+小学四则运算练习软件项目报告
    Week2-作业一——《构建之法》三章精读之想
    虚拟到现实
    脚踏实地,莫问前程
    2016012010 赵瑞雪 散列函数的应用及其安全性
    结对项目报告
    《构建之法》第四章、第十七章读书笔记
    2016012010+小学四则运算练习软件项目报告
    《构建之法》第一、二、十六章读书笔记
  • 原文地址:https://www.cnblogs.com/Robert-Yuan/p/4816643.html
Copyright © 2020-2023  润新知