zoukankan      html  css  js  c++  java
  • P1064 金明的预算方案

    这是2006提高组的一道背包问题,这道题原来这就是有依赖的背包的模板题啊。

    题意为一个01背包,但是有些物品是附件,也就是必须要买附件对应的主件,题目告诉我们每个主件只有0,1,2个附件所以产生了五种情况:1.只买主件  2.买主件+附件1  3.买主件+附件2   4.都买   5.不买。

    那么第一步便是判断是否为主件,不是则存到主件的名下,这里开一个二维的消耗和价值数组,[i[[0]存储主件信息,[i][1],[i][2]分别存附件信息。然后再分情况去进行状态转移求最值,再加一个小剪枝。第四次提交后AC。

    1.熟练掌握有依赖性的背包模板

    2.有n个附件,则策略有2^n+1个选择

    3.预处理一定要思路严谨,方便后续操作

    4.有的时候一维数组记录不了,看看范围,开个二维数组记录也是可以的,找好主件

    代码

    // 
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #define N 100001
    using namespace std;
    int n,T;
    int f[N];//映射的主件 
    int m,v,p; 
    long long value[N][5],weight[N][5];
    long long dp[N];
    int flag[N];
    int main(){
        //有依赖的背包~
        cin>>T>>n;
        for(int i=1;i<=n;i++){
            flag[i]=1;
        }
        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]); 
                    }
                }
            }
        } 
        printf("%d",dp[T]);
        return 0;
    }
    待到oi十一月,我花开后百花杀。
  • 相关阅读:
    DbUtils类的添加,修改,删除
    QueryRunner类的八种结果处理集
    中国传统文化---------斗地主----------
    剑指Offer42 左旋字符串
    剑指Offer41 反转单词顺序,单词字符顺序不变
    剑指Offer40 和为s的连续正数序列
    剑指Offer39 数组中寻找和为sum的两个数字
    剑指Offer36 数字在排序数组中出现的次数
    剑指Offer37 二叉树深度与平衡二叉树判断
    剑指Offer38 数组所有数字出现两次,只有两个出现了一次,找出这两个数字
  • 原文地址:https://www.cnblogs.com/china-mjr/p/11253415.html
Copyright © 2011-2022 走看看