动态规划过程
应用背包问题:分享一下
有一个背包,容量是4磅,现有如下产品

1)要求达到的目标为装入的背包的总价值最大,并且要求重量不能超出
2) 要求转入的物品不能重复
思路分析:算法其实是模型建立的过程
- 分析 建模的过程:
- 横向房物品的重量,从0~4磅
- 纵向是放的物品
第一层,只能放一个吉他
第二层,能放吉他和音响
第三层,吉他,音响和电脑- 依据建模过程,进行背包填表如下图:

- 设计 一个二维数组,i 为行数表示第几行,j为列(表示装入的重量)如上图所示:设计第一行,和第一列为0 不放入任何东西;
- 声明 w[i] ,val[i] 分别表示 第i个物品的重量和价值
w[i] 表示物品的重量 ,代码映射 int [] w={1,3,4},int[] val[]={1500,3000,2000};- int [][] v 变量存放 每个表格存放物品的最大价值
分析得出模型- 构建算法模型,注意考虑!临界条件(边界条件)
条件 :w[i]>j 时 v[i][j]= v[i-1][j]
w[j]<=j 时 v[i][j] =max(v[i-1],v[i]+v[i-1][j-w[i]])
算法的思想: 利用动态规划来解决,每次遍历第i个物品,根据 w[i],v[i] 来决定是否放入到背包中。01问题(只能添加一次,要么有,要么没有)
代码后续补上;
在这里插入代码片
下面展示一些内联代码片
。
package acm;
/**
* @author qxl
*/
public class KnapsackProblem {
public static void main(String[] args) {
knapsack();
}
public static void knapsack(){
// 背包的重量
int [] w={1,4,3};
//背包物品的价值
int [] val={1500,3000,2000};
//表格为4列
int n=w.length;
//表格有5列
int m=val.length;
int[][] v=new int[n+1][m+2];
//表格初初始化,依据分析初始化 表格 第一行和第一列都为空
// 二维数组 v.length 一维数组存放,每个行一维数组的地址
for(int i=0;i<v.length;i++){
v[i][0]=0;
}
// v[0].length 列数
for(int i=0;i<v[0].length;i++){
v[0][i]=0;
}
//遍历打印推演的价值表格
for(int i=0;i<v.length;i++){
for(int j=0;j<v[0].length;j++){
System.out.print(v[i][j]+" ");
}
System.out.println();
}
// 分析出的模型: 当w[i]>j v[i]=v[i-1][j] 注意!!理解 j-w[i] 求出 放入当前行物品后,剩余的重量;i-1 表示当前行上一行
// w[i]<=j v[i]=max{v[i-1][j],v[i]+v[i-1][j-w[i]]}
// O(n^2) 的时间复杂度
//注意 第一行和第一列都为0 因此循环从第一个值开始
for(int i=1;i<v.length;i++){
//体现是思想,建模过程中涉及到的问题
for(int j=1;j<v[0].length;j++){
// 注意!! w 和val 从下标1开始的,这里要注意了 都要进行 i-1;
if(w[i-1]>j){
v[i][j]=v[i-1][j];
}else{
// 由于遍历是从1开始的 因此 w[i]<=j 时候 v[i]= max{v[i-1][j],val[i-1]+v[i-1][j-w[i-1]]} 其中注意! val[i-1]
// w[i-1] 主要是循环下标从1 开始的;
v[i][j]= Math.max(v[i-1][j],val[i-1]+v[i-1][j-w[i-1]]);
}
}
}
//遍历打印推演的价值表格
for(int i=0;i<v.length;i++){
for(int j=0;j<v[0].length;j++){
System.out.print(v[i][j]+" ");
}
System.out.println();
}
}
}