华为机试|HJ16 购物单

HJ16 购物单
分组背包。
因为物品和物品之间存在依附关系,不如将这些物品归位一类(用dfs_create找出这一类),在这一类中挑选出其中一个拿出来当一个物品,纳入到DP的过程中。
分组背包需要注意的是,DP过程中内外层循环的安排。

for(int V=N;V>=0;V--){
    for(int j=0;j<new_groups[i].size();j++){
        auto [cost_0,val_0] = new_groups[i][j];
        if(V>=cost_0) dp[V] = max(dp[V],dp[V-cost_0]+val_0); 
    }
}

代码如下:

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
const int N0 = 65;
int bel[N0];
int cost[N0];
int val[N0];
vector<tuple<int,int,int> > groups[N0];
vector<tuple<int,int> > new_groups[N0];
void dfs_create(int i,int pos,int curCost,int curVal){
    if(pos>=int(groups[i].size())) return ;
    auto [cost,val,id] = groups[i][pos];
    if(id==i){
        dfs_create(i, pos+1, curCost, curVal);
        return ;
    }
    new_groups[i].push_back(tuple<int,int>{curCost+cost,curVal+cost*val});
    dfs_create(i, pos+1, curCost, curVal);
    dfs_create(i, pos+1, curCost+cost, curVal+cost*val);
    return ;
}
int dp[32005];
int main() {
    int N,m;
    cin>>N>>m;
    for(int i=1;i<=m;i++){
        cin>>cost[i]>>val[i]>>bel[i];
        int id = bel[i]==0?i:bel[i];
        groups[id].push_back(tuple<int,int,int>{cost[i],val[i],i});
    }
    for(int i=1;i<=m;i++){
        if(groups[i].size()==0) continue;
        new_groups[i].push_back(tuple<int,int>{cost[i],cost[i]*val[i]});
        dfs_create(i,0,cost[i],cost[i]*val[i]);
    }
   
    for(int i=1;i<=m;i++){
        if(new_groups[i].size()==0) continue;
        for(int V=N;V>=0;V--){
            for(int j=0;j<new_groups[i].size();j++){
                auto [cost_0,val_0] = new_groups[i][j];
                if(V>=cost_0) dp[V] = max(dp[V],dp[V-cost_0]+val_0); 
            }
        }
    }
    cout<<dp[N];
    return 0;
}

晓源算法专栏

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值