最简单直观详细的理解 背包问题 的一维动态规划解法,详见这篇文章最简单直观详细的理解 背包问题 的一维解法 动态规划_一维背包问题_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;
}