• 背包问题


                          背包问题(要不断更新)

    一.01背包

    Q:N物品,T容量,Wi消耗,Vi价值,每件物品取一个,怎样价值最大?(还记得在清北手推了二维的转移方程,但现在并不知道倒序的原理)

        for(int i=1;i<=n;i++){//放到第i件物品 
            for(int j=T;j>=0;j--){//倒序,防止重复往里面放 
                if(j>=weight[i]){
                dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);
                }    
                else{
                    dp[j]=dp[j];
                }    
            }
        }//dp[j]代表当容量为j时的最大价值

    注意:倒序j

    二.完全背包

    Q:N物品,T容量,Wi消耗,Vi价值,每件物品取随意个,怎样价值最大?

        for(int i=1;i<=n;i++){
            for(int j=weight[i];j<=T;j++){
                dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);            
            }
        }

    注意:正序j

    三.多重背包

    Q:N物品,T容量,Wi消耗,Vi价值,每件物品取Ni个,怎样价值最大?

        for(int i=1;i<=n;i++){
            for(int j=T;j>=0;j--){
                for(int k=0;k<=s[i];k++){
                    if(j-k*weight[i]<0)break;
                    dp[j]=max(dp[j],dp[j-k*weight[i]]+k*value[i]);
                }
            }
        }

    二进制优化还不会qaq一定要学会回头再编辑!

    四.二维背包

    Q:N物品,T1容量,T2容量,Wi1消耗,Wi2消耗,,Vi价值,每件物品取1个,怎样价值最大?

        for(int i=1;i<=n;i++){
            for(int j=T1;j>=v[i];j--){
                for(int k=T2;k>=m[i];k--){
                    dp[j][k]=max(dp[j][k],dp[j-v[i]][k-m[i]]+value[i]);
                }
            }
        }

    多加一维,多for一个量的01背包

    五.混合背包

    N物品,T容量,,Wi消耗,,V价值,有的物品取1个,有的物品取随意个,有的物品取s[i]个,怎样价值最大?(s[i]为0为随意)

        for(int i=1;i<=n;i++){
            if(s[i]==0){//完全 
                for(int j=weight[i];j<=T;j++){
                    dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);
                }
            }
            else{//01,多重 
                for(int k=1;k<=s[i];k++){
                    for(int j=T;j>=weight[i];j--){
                        dp[j]=max(dp[j],dp[j-weight[i]]+value[i])
                    }
                }
            }    
        }

    六.分组背包

    N组物品,每组只可以选一个,T容量,怎样取价值最大?

        for(int i=1;i<=n;i++){
            cin>>weight[i]>>value[i]>>x;
            t=max(t,x);//求组数
            b[x]++;//这一组中的序号++ 
            g[x][b[x]]=i;//组里第n个为第i个的信息  
        }
        for(int i=1;i<=t;i++){
            for(int j=T;j>=0;j--){
                for(int k=1;k<=b[i];k++){
                    if(j>=weight[g[i][k]]){
                        dp[j]=max(dp[j],dp[j-weight[g[i][k]]]+value[g[i][k]]);
                    }
                }
            }
        }

    多for组,再for容量,最后for每组的元素,注意预处理

    七.有依赖性的背包

    N物品,里面有主件也有附件,买附件就必须买主件,每个主件最多有两个附件,问怎样价值最大?

        for(int i=1;i<=n;i++){
            cin>>m>>v>>p;
            if(p>0) f[i]=p;
            else if(p==0) f[i]=i;//判断是否为主件 
            //只买主件、主件+附件1,主件+附件2,主件+附件1+附件2,不买    
            if(i==f[i]){
                weight[i][0]=m;//本身 
                value[i][0]=m*v;
            }
            else{//附件 
                if(flag[p]==1){//是第一个附件 
                    weight[p][1]=m;
                    value[p][1]=v*m;
                    flag[p]=2;
                } 
                else if(flag[p]==2){//是第二个附加 
                    weight[p][2]=m;
                    value[p][2]=v*m;
                }                        
            }     
        }
        dp[0]=0;
        for(int i=1;i<=n;i++){
            if(weight[i][0]>0){
                for(int j=T;j>=weight[i][0];j--){
                    if(j>=weight[i][0]){
                    dp[j]=max(dp[j],dp[j-weight[i][0]]+value[i][0]);//只买主件 
                    }
                    if(j>=weight[i][1]+weight[i][0]){                               //只买附件一和.. 
                    dp[j]=max(dp[j],dp[j-weight[i][1]-weight[i][0]]+value[i][1]+value[i][0]);
                    }
                    if(j>=weight[i][2]+weight[i][0]){                                //只买附件二和.. 
                    dp[j]=max(dp[j],dp[j-weight[i][2]-weight[i][0]]+value[i][2]+value[i][0]);
                    }
                    if(j>=weight[i][1]+weight[i][2]+weight[i][0]){        //都买 
                    dp[j]=max(dp[j],dp[j-weight[i][1]-weight[i][2]-weight[i][0]]+value[i][1]+value[i][2]+value[i][0]); 
                    }
                }
            }
        } 
    待到oi十一月,我花开后百花杀。
  • 相关阅读:
    IK分词器插件
    倒排索引
    logstash-安装、基本使用、入门
    Anaconda使用-详解
    java之反射
    Java中级路线jdbc第一天
    Java字符串及字符串的常用方法知识点总结
    Java基本类型的类包装知识点总结
    Java Class类知识点总结
    java异常类知识点总结
  • 原文地址:https://www.cnblogs.com/china-mjr/p/11223149.html
Copyright © 2020-2023  润新知