动态规划 背包问题
让我们才采取动态分析的思路
首先,我们设置一个数组f[n][m] 他的意义是表示前n个物体在背包为m容量状态下的最大价值
当让在运算的时候就分为两种情况,首先
当第n个物品不被放入背包的时候,此时背包的价值和之前n-1个物品的总价值相等
当第n个物品放入背包使,则需要做出一个判断
若是放入背包,那么此时的背包物品总价值为f[n-1][m-v[i]]+w[i]
让他与不放入第n件物品的价值相比较,谁大取谁
下面是具体实现代码
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 1010; int n,m; int f[N][N]; //代表在第n个物品且背包体积为m的情况下的最大价值 int v[N],w[N]; //分别代表第i个物品的体积和价值 int res; int main(){ cin>>n>>m; for(int i = 1; i <= n; i++){ cin>>v[i]>>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-1][j],f[i-1][j-v[i]]+w[i]); } } } res = 0; for(int i = 1; i <= m;i++){ res = max(res,f[n][i]); } cout<<res<<endl; }
之后我们按照原有思路对代码进行优化
首先,我们要明白优化代码的目的,优化代码的目的肯定是减小时间复杂度
在这道题目中,我们可以将二维数组f[n][m]优化成为一维数组,从而大大降低时间复杂度
我们将d[m]的意义定为在n个物品的条件下,背包空间为m的最大价值
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-1][j],f[i-1][j-v[i]]+w[i]); } } }
我们可以将这段代码进行优化,我们在原有代码的基础上,将j由正序变为倒叙,那么我们的f[i-1][j-v[i]]的f[i-1]可以保证
因为倒叙之后,我们的j-v[i]本身便是i-1的值,因为还没有更新
下面是优化后的代码
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 1010; int n,m; int f[N]; int v[N],w[N]; int res; int main(){ cin>>n>>m; for(int i = 1; i <= n; i++){ cin>>v[i]>>w[i]; } for(int i = 1;i <= n; i++){ for(int j = m;j >= v[i]; j--){ f[j] = max(f[j],f[j-v[i]]+w[i]); } } for(int i = 0; i <= m;i++){ res = max(res,f[i]); } cout<<res<<endl; }