动态规划-背包问题

关于动态规划的背包问题,可分为
(1)0/1背包问题
(2)分组背包问题
(3)多重背包问题
(4)完全背包问题

(1)0/1背包问题。

问题描述:有NN件物品和一个容量是 VV的背包。每件物品只能使用一次。
第 ii件物品的体积是 vivi,价值是wi wi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输入描述:第一行两个整数,N,V 用空格隔开,分别表示物品数量和背包容积。
接下来有N行,每行两个数vi,wi,用空格分隔开,表示该物体的体积和价值。
N,V
输出描述: 输出一个整数,表示最大价值。

分析
引入一个(N+1)*(V+1)的二维数组dp[ ][ ]。
dp[i][j]表示把前i个物品【1,i】装入容量为j的背包中获得最大价值
把每个dp[i][j]都看做一个背包;容量为j,装1~i这些物品,最后的dp[N][V]为问题答案。
dp转移方程:
(1)、第i个物品的体积比容量j还大,不能装进背包。直接继承前 i-1 个物品装进容量为j的背包情况即可,即dp[i][j]=dp[i-1][j]。
(2)、第i个物品的体积比容量j小,能装进背包,又可以分成两种情况:装或不装:
①装第i个物品。从前i-1个物品推广,前i-1个物品价值为dp[i-1][j]。第i个背包装进背包后,背包容量减少v[i],价值增加w[i]
有dp[i][j]=dp[i-1][j-v[i]]+w[i]。
②不装第i个物品,有dp[i][j]=dp[i-1][j]。
取两者的最大值:
dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+w[i])

递推代码(暴力做法):
参考代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int w[N], v[N]; //物品的价值和体积
int dp[N][N];
int solve(int n, int V) {
   
   
    for (int i = 1; i <= n; i++)
        for (int j = 0; j <= V; j++) {
   
   
            if (v[i] > j)
                dp[i][j] = dp[i - 1][j];  //第i个物品比背包大,装不了。
            else
                dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - v[i]] + w[i]); //第i个物品能装。
        }
    return dp[n][V];
}
int main() {
   
   
    int n, V;
    scanf("%d%d", &n, &V);
    for (int i = 1; i <= n; i++)
        scanf("%d%d", &v[i], &w[i]);
    printf("%d", solve(n, V));
    return 0;
}

记忆化搜索(暴力做法):
参考代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int w[N], v[N];
int dp[N][N];
int solve(int i, int j) {
   
   
    if (dp[i][j] != 0)
        return dp[i][j];
    if (i == 0)
        return 0;
    int res;
    if (v[i] > j)
        res = solve(i - 1, j);
    else
        res = max(solve(i - 1, j), solve(i - 1, j - v[i]) + w[i]);
    return dp[i][j] = res;
}
int main() {
   
   
    int n, V;
    scanf("%d%d", &n, &V);
    for (int i = 1; i <= n; i++)
        scanf("%d%d", &v[i], &w[i]);
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值