购物单

购物单_牛客网

相当于是比较简单的 有依赖的背包问题,这儿附件最多只有两个,所以枚举起来也方便。

不管是什么样的背包问题变体,一般都是转化为01背包问题进行处理的。先来思考依赖问题,附件不能够单独选,只能和主件搭配在一起,那么本题中对于一个主件,有四种搭配方式:

只选主件,主件+附件1,主件+附件2,主件+附件1+附件2

所以也就只是01背包问题多了几种选择而已。那么解题主要就是分两个步骤了:

  • 构建选择数组(也就是存储所有的选择)
  • 对选择数组进行01背包dp
#include 

using namespace std;

int main(){
    int n, m;
    cin >> n >> m;//钱的总数和物品数量
    n /= 10;//价格是10的整数倍
    //最多只有两个组件,那么第二个维度3代表:主件,附件1,附件2
    vector> price(61, vector(3, 0));//价格
    vector> price_v(61, vector(3, 0));//价格*重要程度
    
    int v, p, q;
    for(int i = 1; i <= m; ++i){ //m个物品
        cin >> v >> p >> q;
        v /= 10; p *= v;//p变为价格*重要程度
        if(q == 0){//是主件
            price[i][0] = v; price_v[i][0] = p;
        }else{//是附件,添加到主件里面去(附件是不能单独选的)
            if(price[q][1] == 0){//第一个附件
                price[q][1] = v; price_v[q][1] = p;
            }else{//第二个附件(最多两个附件)
                price[q][2] = v; price_v[q][2] = p;
            }
        }
    }
    
    //其实就类似01背包的dp,只不过多了几个选择,处理思路是一样的
    //d[i][j]表示只从前i个主件中选取,总钱为j的情况下,所获得的最大 价格*重要程度的和
    vector> dp(m+1, vector(n+1, 0));
    for(int i = 1; i <= m; ++i){//遍历物品
        for(int j = 1; j <= n; ++j){//遍历总钱(相当于01背包的容量)
            int a1 = price[i][0], b1 = price_v[i][0];//主件的价格与价格*重要程度
            int a2 = price[i][1], b2 = price_v[i][1];//附件1
            int a3 = price[i][2], b3 = price_v[i][2];//附件2
            //一共四种选择:只选主件,主件+附件1,主件+附件2,主件+附件1+附件2
            //当然也可以不选
            
            //不选或者只选主件
            if(j >= a1)    dp[i][j] =  max(dp[i-1][j], dp[i-1][j-a1] + b1);
            else dp[i][j] = dp[i-1][j];
            
            //主件 或者 主件+附件1
            if(j >= a1+a2)    dp[i][j] =  max(dp[i][j], dp[i-1][j-a1-a2] +b1+b2);
            else dp[i][j] = dp[i][j];
            
            //主件 或者 主件+附件2
            if(j >= a1+a3)    dp[i][j] =  max(dp[i][j], dp[i-1][j-a1-a3] +b1+b3);
            else dp[i][j] = dp[i][j];
            
            //主件 或者 主件+附件1+附件2
            if(j >= a1+a2+a3)    dp[i][j] =  max(dp[i][j], dp[i-1][j-a1-a2-a3] +b1+b2+b3);
            else dp[i][j] = dp[i][j];
        }
    }
    cout << dp[m][n]*10 << endl;
    return 0;
}

你可能感兴趣的:(牛客题)