学习动态规划,一开始一头雾水,看了好多博客,写的都是不太适合自己,这篇博客写得通俗易懂https://blog.csdn.net/dapengbusi/article/details/7463968。其实懂了思想,写代码写起来就比较简单了。在这里写一下个人的理解:通过把问题分解为更小规模的问题,分到最小的时候肯定会有一个边界,然后从边界开始反过来求解。有点类似于递归,不过动态规划是用数组或者其他的东西,先把小规模的问题的解存入了数组中,就不用重复计算,提高了效率。详细的讲解还是看参考的博客吧https://blog.csdn.net/dapengbusi/article/details/7463968。
package backpack;
//0-1背包问题
//给定n种物品和一背包。物品i的重量是wi,其价值为vi,背包的容量为C。问应如何选择装入背包的物品,使得装
//入背包中物品的总价值最大
//数据:物品个数n=5,物品重量w[n]={2,2,6,5,4},物品价值V[n]={6,3,5,4,6},
public class Package_0_1{
private int c = 10; //背包的容量
private int w[] = {2,2,6,5,4}; //物品的重量
private int v[] = {6,3,5,4,6}; //物品对应的待加
private boolean x[] = new boolean[5]; //记录对应的物品有没有装入背包,false表示没有装入
private int[][] m=new int[5][11]; //状态量,记录最大价值
public Package_0_1() {
}
public void getMaxValue() {
//从最后一行开始填充二维数组m,从左往右,从底往上
int index=w.length-1; //最后一行
for(int j=0;j<=c;j++) {
//j代表的是背包的容量,这里从0开始,到最大容量c=10
//如果背包的容量j大于物品的重量,则可以把物品放入背包,价值当然就是放入物品的价值
if(j>w[index]) {
m[index][j]=v[index];
}
//背包的容量装不下物品,当然价值就是0
else {
m[index][j]=0;
}
}
//接着在最后一行填充的基础上,从倒数第二行开始,从左往右,从底往上填充价值数组m
for(int i=index-1;i>=0;i--) {
for(int j=0;j<=c;j++) {
//如果放得下物品i,则要考虑放入背包的价值大,还是不放的价值大,取最大值
if(j>w[i]) {
m[i][j]=m[i+1][j-w[i]]+v[i]>m[i+1][j]?m[i+1][j-w[i]]+v[i]:m[i+1][j];
}
//如果放不下物品i,则和它的上一次状态相同,也就是它的下一行
else {
m[i][j]=m[i+1][j];
}
}
}
System.out.println("最大价值为:"+m[0][10]);
int j=c;
for(int i=0;i<w.length-1;i++) {
// 如果m[i][j]==m[i+1][j],则表示第i件物品没有放入背包
if(m[i][j]!=m[i+1][j]) {
j=j-w[i];
x[i]=true;
}
}
//对于最后一件物品,如果m[i][j]不为0,就是放入了背包
x[w.length-1]=m[w.length-1][j]==0?false:true;
//输出选择的状态,也就是选择了哪几个物品
for(int i=0;i<x.length;i++) {
if(x[i]) {
System.out.println("选择了第 "+i+" 个物品");
}
}
}
public static void main(String[] args) {
Package_0_1 p=new Package_0_1();
p.getMaxValue();
}
}