经历过拼多多的笔试题,就知道该多学学动态规划算法了。。
问题描述:
有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