背包问题求具体方案

01背包

状态表示与01背包相同
集合分析与01背包完全相同

选择方案的判断,就是看每次方案的选择是哪一个
如果我们此时状态的计算f[i, j]的值是不选第i个物品的价值,即此时最大的价值就是f[i - 1, j],那么我们此时的方案就是不选第i个物品

同理,如果从右边取最大值,我们的答案就是选第i个

即我们判断这个值是等于哪一个来判断第i个物品选还是不选了

这样我们就可以从后往前推一遍来判断某个物品选还是不选了

为什么要从后往前推呢?

只有从后往前推才能逐一的判断从最优解的答案开始往前推

而答案还要保证字典序是最小的,那么我们在选取答案的时候要尽可能的拿到即选

而为了求到这个方案,那么我们上面推到那些就得全部颠倒,即从n到1开始转移,从1-n开始推出方案

#include <iostream>

using namespace std;

int n;
int m;
int f[1010][1010];
int w[1010];
int v[1010];

int main(){
    cin >> n >> m;
    for(int i = 1; i <= n; i++){
        cin >> v[i] >> w[i];
    }
    
    for(int i = n; i; i --){ // 从后往前
        for(int j = 0; j <= m; j++){
            f[i][j] = f[i + 1][j]; // 与正着的意义一样,都是判断上一个选还是不选
            if(j >= v[i]){
                f[i][j] = max(f[i][j], f[i + 1][j - v[i]] + w[i]);
            }
        }
    }
    
    int i = 1, j = m;
    while(i <= n){
        if(j >= v[i] && f[i + 1][j - v[i]] + w[i] >= f[i + 1][j]){
            cout << i << " ";
            j -= v[i];
            i++;
        }
        else{
            i++;
        }
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值