一维数组解01背包问题(总结各种大神的分析)

经历过拼多多的笔试题,就知道该多学学动态规划算法了。。

问题描述:

有n和重量和价值分别为Wi,Vi的物品,从这些物品中挑选出总质量不超过C的物品,如何挑选使得总价值量最大?

思路分析:

序号 weight value 1 2 3 4 5 6 7 8 9 10
a 2 5 0 5 5 8 8 13 13 14 16 16
b 3 3 0 1 3 8 8 9 11 11 14 14
c 5 6 0 1 1 8 8 9 9 9 14 14
d 4 8 0 1 1 8 8 9 9 9 9 9
e 2 1 0 1 1 1 1 1 1 1 1 1

这个表格是自底向上从左到右的顺序,e2单元格表示最多容重2时,只有e物品可选时,最大价值为1

c3表示最多容重为3时,只有c.d.e物品可选时,最大价值为1,因为d和e都大于3,装不了。

a8的值是14,怎么得到?

根据01背包的状态转换方程: f[i,j] = Max{ f[i-1,j-Wi]+Pi( j >= Wi ),  f[i-1,j] }

f[i-1][j]表示b[8]的值为11,f[i-1],j-wi]表示b6的值为9,9+5=14>11,因此a8的值为14。

分析原文地址:https://blog.csdn.net/mu399/article/details/7722810

当背包容量为j时,已经放入了i件物品,最大价值为d[i]d[j]

当第i件物品比背包容量还大时,不能放,所以,d[i][j]=d[[i-1][j];

当第i件物品比背包容量小时,就要判断两种情况:不放的话,和上式相同,放的话,背包容量-第i件物品的质量再去装前i-1件物品,所得得最大价值加上第i件物品的价值,两者较大值即为最优解。d[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i])

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
#define EMPTY
#define INF -65536
const int C=10;//容量capability
int n;//物品个数
int w[15],v[15];//物品个数,物品质量weight,物品价值value
int dp[1000][C+1]={0};
int main(){
    scanf("%d ",&n);
    for(int i=1;i<=n;i++)scanf("%d",&w[i]);
    for(int i=1;i<=n;i++)scanf("%d",&v[i]);
    #ifdef EMPTY//要求价值最大化,可以不满
        for(int i=0;i<=n;i++)dp[i][0]=0;
        for(int i=0;i<=C;i++)dp[0][i]=0;
    #else//必须装满
        dp[0][0]=0;
        for(int i=1;i<=C;i++)dp[0][i]=INF;
        for(int i=1;i<=n;i++)dp[i][0]=INF;
    #endif
     for(int i=1;i<=C;i++){
         for(int j=1;j<=n;j++){
             dp[i][j]=w[j]<=i?max(dp[i][j-1],dp[i-w[j]][j-1]+v[j]):dp[i][j-1];
         }
     }
     cout<<dp[C][n]<<endl;
    return 0;
}


从空间花费从大到小来构成for循环的话,就可以直接用一维数组来保存物品数-1 的值。

当背包容量为j时,已经放入了i件物品,最大价值为d[j]

当第i件物品比背包容量还大时,d[j]=d[j];

当第i件物品比背包容量小时,就要判断两种情况:不放的话,和上式相同,放的话,背包容量-第i件物品的质量再去装前i-1件物品,所得得最大价值加上第i件物品的价值,两者较大值即为最优解。d[j]=max(dp[j],dp[j-w[i]]+v[i])

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
#define EMPTY
#define INF -65536
const int C=10;//容量capability
int n;//物品个数
int w[15],v[15];//物品个数,物品质量weight,物品价值value
int dp[C+1];
int main(){
    scanf("%d ",&n);
    for(int i=1;i<=n;i++)scanf("%d",&w[i]);
    for(int i=1;i<=n;i++)scanf("%d",&v[i]);
    #ifdef EMPTY//要求价值最大化,可以不满
        for(int i=0;i<=C;i++)dp[i]=0;
    #else//必须装满
        dp[0]=0;
        for(int i=1;i<=C;i++)dp[i]=INF;
    #endif
     for(int i=1;i<=n;i++){
         for(int j=C;j>0;j--){
             dp[j]=w[i]<=j?max(dp[j],dp[j-w[i]]+v[i]):dp[j];//注意这个+v[i]是在dp[]外面加的
         }
     }
     cout<<dp[C]<<endl;
    return 0;
}


代码博文地址:https://blog.csdn.net/stack_queue/article/details/52734100

猜你喜欢

转载自blog.csdn.net/zonahaha/article/details/81168244