#dp动态规划01背包问题
首先我们先了解一下动态规划问题主要将的是什么:
有 NN 件物品和一个容量为 V 的背包,每件物品有各自的价值且只能被选择一次,要求在有限的背包容量下,装入的物品总价值最大。
「0-1 背包」是较为简单的动态规划问题,也是其余背包问题的基础。
动态规划是不断决策求最优解的过程,「0-1 背包」即是不断对第 ii 个物品的做出决策,「0-1」正好代表不选与选两种决定。
背包问题可以分为两个步骤:一个是状态表示,一个是状态计算。状态表示和计算我们可以用一个二维数组分f[N][N] 表示,其中N是问题中物品的最大数量,每一个状态可以用f[i][j] 来表示其中i表示前 i 个物品并且体积不超过 j 的最优解。
当前的状态依赖于之前的状态,可以理解为从初始状态f[0][0] = 0开始决策,有 NN 件物品,则需要 NN 次决 策,每一次对第 ii 件物品的决策,状态f[i][j]不断由之前的状态更新而来。
(1)当前背包容量不够(j < v[i]),没得选,因此前 ii 个物品最优解即为前 i−1i−1 个物品最优解:
对应代码:f[i][j] = f[i - 1][j]。
(2)当前背包容量够,可以选,因此需要决策选与不选第i 个物品:
选:f[i][j] = f[i - 1][j - v[i]] + w[i]。
不选:f[i][j] = f[i - 1][j] 。
我们的决策是如何取到最大价值,因此以上两种情况取 max()
v输入存的是每件物品的体积,w数组存的是每件物品的价值。
下面是完整代码:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1010;
int f[N][N];
int v[N];
int w[N];
int n,m;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>v[i];
cin>>w[i];
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
f[i][j]=f[i-1][j];
if(j>=v[i]) f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i]);
}
}
cout<<f[n][m];
return 0;
}