[有依赖的背包问题] 金明的预算方案 P1064 洛谷

https://www.luogu.org/problemnew/solution/P1064
有依赖背包的入门题 除了树形DP 就是这了
非树形有依赖的背包问题(只有两类物品:主件,附件)有主件才可以选附件

首先我们注意到对于每一个主件,有很多种购买的方案:可以不买,可以只买主件,或者买主件外加几种附件,当附件个数较少的时候枚举就可以过

但我们正解的话,可以先对每种主件的 附件的集合 进行一次 01 背包处理,就可以先求出 对于每一种主件包括其附件的组合中,每种花费的最大价值

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <list> 
using namespace std;
typedef long long ll;

const int maxn = 100+5 ;
const int maxv = 32000+5;
const int mod = 1000000 ;
const int INF = 0x3f3f3f3f;
const double PI=acos(-1.0);

int n,m,d,x,y,flag;
int v,p,q;
pair<int,int>w[maxn]; // 存只出现一次主件没有配件的 
vector<pair<int,int> >groups[maxn]; // 处理完放这里 然后DP
int dp[maxv];

int main(){
    scanf("%d %d",&n,&m);
    for(int i=0;i<=m;i++) groups[i].push_back(make_pair(0,0));// 初始化第一个是0用来只放主件
    for(int i=1;i<=m;i++){ //之后第一次放这里的就是只选主件的价值和容量
        scanf("%d %d %d",&v,&p,&q);
        if(q==0){
            w[i].first=v;w[i].second=p*v;
        }else{
            int len=groups[q].size(); // 先录入附件
            for(int j=0;j<len;j++){ // 之后再录入他的附件就会遍历这里 
                int cost=groups[q][j].first+v; //选第一个第二个 
                int val=groups[q][j].second+p*v; //或者和之前已经组合的 1和附件 在组合 放到这层vector后
                groups[q].push_back(make_pair(cost,val));
            }
        }
    }
    for(int i=1;i<=m;i++){ // 这里吧主件价格和容量 补进去
        for(int j=0;j<groups[i].size()&&w[i].first;j++){
            groups[i][j].first+=w[i].first;
            groups[i][j].second+=w[i].second;
        }
    }
    for(int i=1;i<=m;i++){ // 01背包 先dp 组合
        for(int j=n;j>=0&&groups[i].size();j--){ // 组合内在01背包
            for(int k=0;k<groups[i].size();k++){
                if(j>=groups[i][k].first){
                    dp[j]=max(dp[j],dp[j-groups[i][k].first]+groups[i][k].second);
                }
            }// 在j价格下 然后 i 组合 第k类下处理完 最大值
        }
    }
    printf("%d\n",dp[n]);
    return 0;
}
全部评论

相关推荐

2025-12-28 20:47
已编辑
北京工商大学 Java
程序员牛肉:我靠你这个实习经历其实最需要担心的点是你做的太多了,可能会被面试官怀疑是你伪造的。 交易状态机是你做的,支付多渠道是你做的,对账是你做的,结算还是你做的,重复支付也是你做的,整个服务的异常处理也是你做的。 其实你这个反而问题很大的,你想想站在面试官的角度,他是真的会相信你的能力很强,还是相信这份实习你伪造了大部分?我相信你真的做了这么多,但是删一些,废话删一删。你这个做的太多了反而真实性不可信。 后面再补一个项目,在github上找一个高star的项目学一学然后写到自己简历上。我觉得你能力肯定没问题。28届能做到这个份上很厉害,但是在求职市场中,你不是在跟28届的同学比,把你这个简历放到27届其实也就一般水平。 所以后续要想一想看看能不能给自己简历上搞点亮点,比如开源贡献呢?比如博客呢?
实习要如何选择和准备?
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务