介绍
学习动态规划算法的经典例题。
动态规划算法一般有3个特征
1、最优化原理:最优解所包含的子问题的解也是最优的。
2、无后效性:就是后面问题的解决不引起前面问题解的变动,或者说不影响前面问题的解。
3、重叠子问题:就是说各子问题之间互相关联,即,以后问题的解可能会重复用到前面子问题的解。
另外,动态规划的输出往往依赖于链表的回溯。
思路
现在要达到的目的就是要求出在当前现有商品和背包容量的条件下如果才能使价值最高。
1、如果背包除了能装下当前物品外还有剩余容量的话,那么可以在刨去当前物品的情况下去找当背包容量等于这个剩余容量的值的时候的最优解。如果当前物品的价值+剩余容量的最优解优于刨去当前物品的当前背包容量的最优解的时候,那么当前物品在当前背包容量条件下的更优解就找到了。否则保持原样不变。
2、如果背包刚好能装下当前物品,那就直接跟刨去当前物品在当前背包容量条件下的最优解进行比较。如果优于这个最优解就更新在当前物品当前背包容量的前提下的最优解,否则保持不变。
3、根本装不下,于是直接保持原来最优解不变。
用法
package com.company;
public class Main {
public static void main(String[] args) {
// write your code here
Good[] goodsArray = {
new Good("水",10,3),
new Good("书",3,1),
new Good("食物",9,2),
new Good("夹克",5,2),
new Good("相机",6,1)
};
Good[] goodsArray0 = {
new Good("吉他",1500,1),
new Good("音响",3000,4),
new Good("笔记本电脑",2000,3)
};
Bag.bagSolution(goodsArray,6);
}
}
输出
解集:
0 0 10 10 10 10
3 3 10 13 13 13
3 9 12 13 19 22
3 9 12 14 19 22
6 9 15 18 20 25
背包中物品价值最高为:25
相机 价值:6 重量:1
食物 价值:9 重量:2
水 价值:10 重量:3
Process finished with exit code 0
实现
package com.company;
public class Bag {
/**
* 动态规划算法最著名的背包问题
* 每次装背包时只需要知道当背包重量排除某物品时
* 加上余下空余重量的最优解才能得到当前的解。
* 如果当前的解比已经得到同重量背包解更优就更新改重量背包的最优解。
* 比较麻烦的是列举出背包中有哪些物品。
* 也是用单链表,如果某单元格并不添加新物品则指针指向上面的单元格。
* 否则指向左上边对应的单元格
* 但是第一行要特殊处理。
* @param goodsArray
* @param bagSize
*/
static public void bagSolution(Good[] goodsArray,int bagSize) {
if (bagSize <= 0 || goodsArray.length <= 0) {
System.out.println("无解");
return;
}
BestSolution[][] answerArray = new BestSolution[goodsArray.length][bagSize];
for (int counter = 0;counter < goodsArray.length;counter++)
for (int counter0 = 0;counter0 < bagSize;counter0++)
answerArray[counter][counter0] = new BestSolution();
for (int counter = 0;counter < goodsArray.length;counter++) {
for (int counter0 = 0;counter0 < bagSize;counter0++) {
int remainingWeight = counter0 - goodsArray[counter].getWeight() + 1;
if (remainingWeight > 0) {
//有剩余空间
if (counter - 1 >= 0) {
//如果不是第一行
if (answerArray[counter - 1][remainingWeight - 1].getMaxValue() + goodsArray[counter].getValue() > answerArray[counter - 1][counter0].getMaxValue()) {
answerArray[counter][counter0].goodPointer = goodsArray[counter];
answerArray[counter][counter0].prePointer = answerArray[counter - 1][remainingWeight - 1];
answerArray[counter][counter0].setMaxValue(answerArray[counter - 1][remainingWeight - 1].getMaxValue() + goodsArray[counter].getValue());
} else {
answerArray[counter][counter0].prePointer = answerArray[counter - 1][counter0];
answerArray[counter][counter0].setMaxValue(answerArray[counter - 1][counter0].getMaxValue());
}
} else {
//是第一行
answerArray[counter][counter0].goodPointer = goodsArray[counter];
answerArray[counter][counter0].setMaxValue(goodsArray[counter].getValue());
}
} else if (remainingWeight == 0){
//刚好装下
if (counter - 1 >= 0) {
if (goodsArray[counter].getValue() > answerArray[counter - 1][counter0].getMaxValue()) {
answerArray[counter][counter0].goodPointer = goodsArray[counter];
answerArray[counter][counter0].setMaxValue(goodsArray[counter].getValue());
} else {
answerArray[counter][counter0].prePointer = answerArray[counter - 1][counter0];
answerArray[counter][counter0].setMaxValue(answerArray[counter - 1][counter0].getMaxValue());
}
} else {
answerArray[counter][counter0].goodPointer = goodsArray[counter];
answerArray[counter][counter0].setMaxValue(goodsArray[counter].getValue());
}
} else {
//根本装不下
if (counter - 1 >= 0) {
answerArray[counter][counter0].prePointer = answerArray[counter - 1][counter0];
answerArray[counter][counter0].setMaxValue(answerArray[counter - 1][counter0].getMaxValue());
}
}
}
}
System.out.println("解集:");
for (int counter = 0;counter < goodsArray.length;counter++) {
for (int counter0 = 0;counter0 < bagSize;counter0++) {
System.out.print(answerArray[counter][counter0].getMaxValue() + "\t");
}
System.out.println();
}
System.out.println("背包中物品价值最高为:" + answerArray[goodsArray.length - 1][bagSize - 1].getMaxValue());
BestSolution headPointer = answerArray[goodsArray.length - 1][bagSize - 1];
while (headPointer != null) {
if (headPointer.goodPointer != null)
System.out.println(headPointer.goodPointer.getGoodName() + "\t价值:" + headPointer.goodPointer.getValue() + "\t重量:" + headPointer.goodPointer.getWeight());
headPointer = headPointer.prePointer;
}
}
}
package com.company;
public class BestSolution {
public Good goodPointer = null;
public BestSolution prePointer = null;
private int maxValue = 0;
public BestSolution() {
}
public int getMaxValue() {
return maxValue;
}
public void setMaxValue(int maxValue) {
this.maxValue = maxValue;
}
}
package com.company;
public class Good {
private String goodName;
private int value;
private int weight;
public Good nextPointer = null;
public Good(String goodName, int value, int weight) {
this.goodName = goodName;
this.value = value;
this.weight = weight;
}
public String getGoodName() {
return goodName;
}
public int getValue() {
return value;
}
public int getWeight() {
return weight;
}
}