算法——动态规划——背包问题——二维动态规划解法

最简单直观详细的理解 背包问题 的一维动态规划解法,详见这篇文章最简单直观详细的理解 背包问题 的一维解法 动态规划_一维背包问题_Bule Guy的博客-CSDN博客

我们从题切入,先看题目要求:

解题思路:

1:我们用到了二维数组,将f[i][j]表示为:将前i个物品放到了总体积为j的包里的情况下,包的最大总价值。

2:那么我们f[i][j]的表示方法如下:

针对第i个物品,我们有两种情况:

      一:不放第i个物体:f[i][j]=f[i-1][j];

      二:放第i个物体:f[i][j]=f[i-1][j-v[i]]+w[i];

          所以f[i][j]=max{情况一,情况二},即f[i][j]=max{ f[i-1][j], f[i-1][j-v[i]]+w[i] }

基本思路就是如此,下面我们举个例子来帮助大家更好理解:

现在有三个物体,体积价值如下表:

那么我们可以根据f[i][j]这个二位数组得到一个表格:

表格的第一行,我们可以很轻松的写出来

根据第一行得出的数据和上面我们说的公式f[i][j]=max{ f[i-1][j], f[i-1][j-v[i]]+w[i] },我们可以退推出来剩下所有的表格内容:

示例:上图中绿色表格中内容应该为多少呢?

首先,该表格为f[2][3],那么f[2-1][3]我们根据第一行可知为6,f[1][3-2]+w[2]为16,取两个之间的最大值,所以图中绿色表格数值应为16。

如此下去,整个表格的所有内容都可以得出,即二维数组f[i][j]所有值都可以得出来,所以f[N][V]就可以得出来。

代码如下:

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;
const int N=1010;
int n,m;//n个物品,背包容量为m
int f[N][N];
int v[N],w[N];//物体的体积和价值
int main(){
    cin>>n>>m;
    //输入物体体积和价值
    for(int i=1;i<=n;i++)//数列下标从1开始,而不是0
    {
        cin>>v[i]>>w[i];
    }
    
    //初始化第一行,这段代码删去其实也可以,只需要将下面初始其他行的代码i的初始值从2改成1即可
    for(int i=0;i<=m;i++)
    {
        //f[1][i]=v[1]<=i?w[1]:0;
        f[1][i]=v[1]<=i?w[1]:0;
    }
    
    //初始化其他行
    for(int i=2;i<=n;i++)
    {
        for(int j=0;j<=m;j++)
        {
            f[i][j]=f[i-1][j];
            //第i个物体重量小于包总容量再考虑将第i个放入包内
            if(v[i]<=j)
            {
                f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i]);
            }
        }
    }
    //输出最终结果
    cout<<f[n][m]<<endl;
    return 0;
    
    
    
}

最简单直观详细的理解 背包问题 的一维动态规划解法,详见这篇文章​​​​​​​最简单直观详细的理解 背包问题 的一维解法 动态规划_一维背包问题_Bule Guy的博客-CSDN博客

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值