动态规划 背包问题

 

让我们才采取动态分析的思路

首先,我们设置一个数组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;
}

 

posted @ 2022-10-11 22:01  软工小蜗牛  阅读(50)  评论(0编辑  收藏  举报