01背包问题

问题描述

题目来源(AcWing #2_01背包问题)在这里插入图片描述

思路

1.状态表示:dp[i][j]表示从前i个物品中选择总体积小于等于j的若干物品最大价值和是多少
2.动态转移:考虑计算第i个物品时有以下两种情况(下述中v表示第i件物品体积,w表示第i件物品价值)
–>a.包含第i个物品:dp[i-1][j-v]+w
–>b.不包含第i个物品:dp[i-1][j]
dp[i][j] = max{a, b};

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXN = 1005;
int v[MAXN], w[MAXN];       //v表示体积,w表示价值
int dp[MAXN][MAXN];         //dp[i][j]表示从前i个物品中选择总体积小于等于j的若干物品最大价值和是多少
int main() {
    int N, V;
    cin >> N >> V;
    for(int i = 1; i <= N; i++) {
        cin >> v[i] >> w[i];
    }
    
    for(int i = 1; i <= N; i++) {
        for(int j = 0; j <= V; j++) {    
            //在考虑包不包含i时,背包容量应必须大于第i件物品体积,否则必定有dp[i][j] = dp[i-1][j]
            if(j < v[i]) {
                dp[i][j] = dp[i-1][j];
            }else {
                dp[i][j] = max(dp[i-1][j], dp[i-1][j-v[i]] + w[i]);
            }
        }
    }
    //dp[N][V]表示前N个物品(即所有物品)中选择总体积小于等于V(即尽量装满背包体积)的若干物品最大价值和(即答案)
    cout << dp[N][V] << endl;
    return 0;
}
空间优化

在这里插入图片描述
观察动态转移方程式可以发现,在计算第i个物品的价值时,只用到了i-1个物品且体积小于等于j时的价值(这点很重要),可考虑去除不必要的空间,将二维降至一维。如下图直接降维:
在这里插入图片描述
对于j<v[i]时,转移方程式变为了没有意义的恒等式,所以可以直接在循环时控制保证体积足以装入第i件物品。同时,如果依然让表示体积的j从小到大循环,那么dp[j-v[i]]表示的则是二维的dp[i][j-v[i]],而我们需要用到的是dp[i-1][j-v[i]],所以为了避免在计算第i件物品覆盖了保存的第i-1个物品时的情况,让体积从大到小(V~0)循环(可配合上述标注的重要点思考)。即动态转移如下图:
在这里插入图片描述

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXN = 1005;
int v[MAXN], w[MAXN];       //v表示体积,w表示价值
int dp[MAXN];         //dp[j]表示从前i个物品(在外层循环中控制)中选择总体积小于等于j的若干物品最大价值和是多少
int main() {
    int N, V;
    cin >> N >> V;
    for(int i = 1; i <= N; i++) {
        cin >> v[i] >> w[i];
    }
    
    for(int i = 1; i <= N; i++) {
        for(int j = V; j >= v[i]; j--) {    
            dp[j] = max(dp[j], dp[j-v[i]] + w[i]);
        }
    }
    //dp[N][V]表示前N个物品(即所有物品)中选择总体积小于等于V(即尽量装满背包体积)的若干物品最大价值和(即答案)
    cout << dp[V] << endl;
    return 0;
}
初始化问题

对于体积和不超过背包的情况时,初始化dp[0~V]都初始化为0,即表示最终状态可由任意一体积状态转移而来。比如由k体积转移而来,且dp[k] = 0,则表示最终状态背包依然有k体积的空余。
对于体积恰好装满背包的情况时,初始化dp[0~V]为负无穷大,dp[0]为0。则对于最终状态,如果由某一有空余空间的状态转移而来时,则负无穷大+任意数依然为负无穷大,最终状态也变为了负无穷大的不合法值。只有当从0状态转移时,最终状态才表示为合法值(即背包无空余空间)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值