背包问题(0-1背包、完全背包、多重背包)

本文详细介绍了背包问题的三种类型:0-1背包、完全背包和多重背包。针对每种类型,文章阐述了问题描述,提供了动态规划的思路分析,并给出了相应的代码实现。动态规划是解决这些问题的关键,通过状态转移方程,求解物品的最大价值。
摘要由CSDN通过智能技术生成

0-1背包问题

问题描述:

n件物品,每件物品重量为w[i],价值为v[i],现有一个容量大小为m的背包,如何选择使得背包内物品价值最大

思路(动态规划):
  1. 设置二维数组dp[][],令dp[i][j]表示前i件物品容量为j的背包所能获得的最大价值,则dp[n][m]为所求解;

  2. 只考虑第i件物品,可将情况分为放入或者不放入两种:
    2.1
    对容量j的背包,不放入第i件物品,则问题转化为将前i-1个物品放入容量为j的背包的问题 ,即dp[i][j] = dp[i-1][j]

    2.2
    对容量j的背包,若放入第i件物品,则当前背包容量就变成j-w[i],得到第i件物品的价值v[i],问题转为将前i-1件物品装入容量为j-w[i]的背包的问题,即dp[i][j] = dp[i-1][j-w[i]]+v[i];
    故状态转移方程为:
    dp[i][j] = max( dp[i-1][j], dp[i-1][j-w[i]]+v[i] );

  3. 对于边界情况,显然得出有 dp[i][0] = 0, dp[0][j] = 0;(0 <= i <= n; 0 <= j <= m);

  4. 观察状态转移方程,第i件物品的取值仅与第i-1件物品的选取有关,故可将二维数组优化为一维数组,并用如下状态转移方程:
    dp[j] = max( dp[j], dp[[j-w[i]]+v[i] );
    注意:
    根据未优化的状态转移方程:dp[i][j]用到的是dp[i-1][…]的数据,因此我们在更新dp[j]的时候必须确保dp[j]以及dp[j-w[i]]是第i-1轮的数据,因此更新dp[j]时必须要逆序更新,即倒序遍历j的值

代码:
#include <iostream>

using namespace std;
const int MAXN = 1001;

int dp[MAXN];//下标表示容量,内容表示价值;在不同题目中,指代内容可更改,思路最重要
int w[MAXN];//物品重量
int v[MAXN];//物品价值

int main()
{
   
    int n,m;//n件物品,容量为m
    while(cin >> n >> m)
    {
   
        for(int i=0; i<n; i++)//输入
        {
   
            cin >> w[i] >> v[i];
        }

        for(int i=0; i<=m; i++)//初始化dp数组,注意i<=m,要更新到m
        {
   
            dp[i] = 0;
        }

        for(int i=0; i<n; i++)//依次判断第i件物品
        {
   
            for(int j=m; j >= w[i]; j--)//逆序更新; j>=w[i]是为了保证 dp[j-w[i]]下标不为负
            {
   
                dp[j] = max(dp[j], dp[
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值