Dynamic programming algorithm-----Introduction

Dynamic programming

Case-backpack problem

There is a backpack with a capacity of 4 pounds, and the following items are available

article weight price
Guitar G 1 1500
Sound S 4 3000
Computer L 3 2000

Required to achieve the target value of the total of the maximum load of the backpack, and the weight does not exceed the
required load of the article can not be repeated

Introduction to dynamic programming

  1. The core idea of ​​the dynamic programming (Dynamic Programming) algorithm is: divide the big problem into small problems to be solved, so as to obtain the optimal solution step by step .

  2. The dynamic programming algorithm is similar to the divide-and-conquer algorithm . Its basic idea is to decompose the problem to be solved into several sub-problems, first solve the sub-problems, and then obtain the solution of the original problem from the solutions of these sub-problems.

  3. Unlike the divide-and-conquer method , it is suitable for problems that are solved by dynamic programming, and the sub-problems obtained by decomposition are often not independent of each other . ( That is, the solution of the next sub-stage is based on the solution of the previous sub-stage , and further solutions are performed)

  4. Dynamic planning can be gradually advanced by filling in the form to obtain the optimal solution.

Thinking analysis

The backpack problem mainly refers to a backpack with a given capacity and a number of items with a certain value and weight. How to choose items to put in the backpack to maximize the value of the items. Among them, it is divided into 01 backpack and complete backpack (a complete backpack refers to : each item has unlimited pieces available)

The main idea of ​​the algorithm is solved by dynamic programming. For the i-th item that is traversed each time, determine whether the item needs to be put into the backpack according to w[j and v[j . That is, for a given n items, let v[i] and w[i] be the value and weight of the i-th item, respectively, and C be the capacity of the backpack. Let v[i][j denote the maximum value that can be loaded into the backpack of capacity j in the first i items. Then we have the following result:

v[i][0]=v[0][j]=0;//表示填入表的第一行和第一列是0
当w[i]> j时: v[i][j]=v[i-1][j]//当我们加入的新的商品容量大于当前背包的容量时,就直接使用上一个单元格的装入策略
当j>=w[i]: v[i][j]=max(v[i-1][j]),v[i-1][j-w[i]]+v[i]}
//当准备加入的新的商品下雨等于当前背包的容量时,
//v[i-1][j]就是上一个单元格的装入最大的值 
//v[i]当前商品的价值
//v[i-1][j-w[i]]装入i-1个商品到剩余空间j-w[i]的最大值

Backpacking process

article 0 lbs 1 2 3 4
0 0 0 0 0
Guitar G 0 1500G 1500G 1500G 1500G
Sound S 0 1500G 1500G 1500G 3000S
Computer L 0 1500G 1500G 2000L 3500G+L

1. If there is only a guitar , no matter how large the backpack is, you can only put one guitar

2. If there are guitars and stereos , only guitars can be placed in the front, and the stereos can only be placed when the backpack capacity is 4 pounds.

. . . . . . . The rest is the same

Verify our above formula

v[1] [1] = 1500;
1.i=1,j=1
2.w[i] = w[1] =1
w[1]=1  j=1   当j>=w[i]: v[i][j]=max(v[i-1][j]),v[i-1][j-w[i]]+v[i]}
v[1][1] = max {
    
    v[0][1],v[1]+v[0][1-1]} = max{
    
    0,1500+0} = 1500

v[3][4]
    i = 3,j = 4 
w[i] = w[3] = 3  j=4
v[3][4] = max {
    
    v[2][4],v[3]+v[2][1]} = max{
    
    3000,2000+1500} = max{
    
    3000,3500}=3500

Code

package 算法;
//动态规划   ----   背包问题
public class dynamic {
    
    

	public static void main(String[] args) {
    
    
		// TODO Auto-generated method stub
		int[] w = {
    
    1,4,3};//物品重量
		int[] val = {
    
    1500,3000,2000};//对应的物品价格
		int m = 4;//背包容量
		int n = val.length;//物品个数
		
		//为了记录放入商品的情况
		int[][] path = new int[n+1][m+1];
		
		//创建二维数组
		int[][] v = new int[n+1][m+1];
		//初始化表格第一行和第一列
		for(int i=0;i < v.length;i++){
    
    
			v[i][0] = 0;//将第一列 置为0
		}
		for(int i=0;i < v[0].length;i++){
    
    
			v[0][i] = 0;//将第一行设置为0
		}
		//根据前面得到的公式来动态规划处理
		for (int i = 1; i < v.length; i++) {
    
    //不处理第一行
			for (int j = 1; j < v[0].length; j++) {
    
    //不处理第一列
				//公式
				if(w[i-1]>j){
    
       //因为我们的i是从1开始的,因此原来的w[i]修改成w[i-1]
					v[i][j] = v[i-1][j];
				}else{
    
    
					//因为我们的i是从1开始的,因此val[i]应该改成val[i-1]
					//v[i][j] = Math.max(v[i-1][j], val[i-1]+v[i-1][j-w[i-1]]);
					//为了记录商品存放到背包的情况,我们不能直接的使用上面的公式,需要if-else来提现
					if(v[i-1][j] < val[i-1]+v[i-1][j-w[i-1]]){
    
    
						v[i][j] = val[i-1]+v[i-1][j-w[i-1]];
						//把当前的情况记录到path
						path[i][j] = 1;
					}else{
    
    
						v[i][j] = v[i-1][j];
					}
				}
			}
		}
		//输出下我们的表格  看看情况
		for (int i = 0; i < v.length; i++) {
    
    
			for (int j = 0; j < v[i].length; j++) {
    
    
				System.out.print(v[i][j]+" ");
			}
			System.out.println();
		}
		//输出最后我们放入的那些商品
		//遍历path		这样会把所有情况得到,我们只需要最后的情况
//		for (int i = 0; i < path.length; i++) {
    
    
//			for (int j = 0; j < path[i].length; j++) {
    
    
//				if(path[i][j]==1){
    
    
//					System.out.println("第"+i+"个商品放入背包");
//				}
//			}
//		}
		int i = path.length-1;			//行的最大下表
		int j = path[0].length-1;		//列的最大下表
		while(i>0 && j>0){
    
    //从后向前遍历
			if(path[i][j] == 1){
    
    
				System.out.println("第"+i+"个商品放入背包");
				j-=w[i-1];
			}
			i--;
		}

		
	}

}
0 0 0 0 0 
0 1500 1500 1500 1500 
0 1500 1500 1500 3000 
0 1500 1500 2000 35003个商品放入背包1个商品放入背包

Guess you like

Origin blog.csdn.net/qq_22155255/article/details/113869218