问题:购物车体积为13,求能选择的最大价值
P[i,c]:i代表i商品,c代表剩余体积
Vi:第i个商品的体积,Pi:第i个商品的价格
P[i,c]=max{p[i-1,c-vi]+pi,p[i-1,c]}
即:比较选i时的价值(p[i-1,c-vi]+pi)和不选i时的价值(p[i-1,c])的大小,选择价值最大的
首先初始化当i=0时或c=0时P[i,c]都为0
最后一个点就是最优解
过程如下
记录拿不拿此商品的决策过程
选择了商品i,即价值为p[i-1,c-vi]+pi,则Rec[i,c]=1。
若没有选择商品i,则价值为p[i-1,c],则Rec[i,c]=0。
伪代码
从最后一个格子开始倒序判断是否选择商品
动态规划解题步骤
代码为:
//一共有5个商品,购物车体积为13,求能选择的最大价值
public class BackPack {
public static void main(String[] args) {
int[] v = {10,3,4,5,4}; //商品的体积
int[] pic = {24,2,9,10,9}; //商品的价值
int[][] P = new int[6][14]; //用于记录递推过程(第1个坐标值的(1-5)代表5个商品,第2个坐标值的(1-13)代表购物车的体积)
int[][] rec = new int[6][14]; //记录决策过程
//初始化时设置当商品为0时或当购物车体积为0时P[][]都为0,因为后面递推时需要用到这些数据
for (int i = 0; i < P.length; i++) {
P[i][0] = 0;
}
for (int j = 0; j < P[0].length; j++) {
P[0][j] = 0;
}
for (int i = 1; i < 6; i++) { //商品编号1-5
for (int j = 1; j < 14; j++) { //购物车体积1-13
if(v[i-1]<=j&&P[i-1][j-v[i-1]]+pic[i-1]>P[i-1][j]){ //v[i-1]<=j:背包可以装下商品i
//P[i-1][j-v[i-1]]+pic[i-1]:装下商品i时的价值,P[i-1][j]:没装商品i时的价值
P[i][j] = P[i-1][j-v[i-1]]+pic[i-1]; //装下时价值大于没装时,则P[i][j]放装下时的价值
rec[i][j] = 1; //选择了商品,则置此时标志为1
}else{
P[i][j] = P[i-1][j]; //装下时价值小于没装时,则P[i][j]放没装下时的价值
rec[i][j] = 0; //没选择商品,则置此时标志为0
}
}
}
System.out.println("备忘录为:");
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 14; j++) {
System.out.print(P[i][j]+"\t");
}
System.out.println();
}
//备忘录的最后一个元素即为结果
System.out.println("最大价值为:"+P[5][13]);
System.out.println("决策过程为:");
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 14; j++) {
System.out.print(rec[i][j]+"\t");
}
System.out.println();
}
System.out.println("选择的商品编号为:");
int volume = 13;
for (int i = 5; i >0 ; i--) {
if(volume-v[i-1]>=0&&rec[i][volume]==1){
volume = volume-v[i-1];
System.out.print(i+"\t");
}
}
}
}