1, Dynamic programming
Dynamic Programming (DP) is a branch of operations research, which is the process of solving the optimization of decision-making process.
2, Basic thought
(1) divide the large problem into small problems to solve, so as to obtain the optimal solution step by step;
(2) the dynamic programming algorithm is similar to the divide and conquer method. Its basic idea is to decompose the problem to be solved into several sub problems. First solve the sub problems, and then get the solution of the original problem from the solutions of these sub problems.
(3) different from the divide and conquer method, the sub problems obtained by decomposition are often not independent of each other. (that is, the next solution is based on the optimal solution obtained last time)
(4) a table can be used to record the answers of all solved sub questions. No matter whether the subproblem is used in the future, as long as it is calculated, the results will be filled in the table. There are many specific dynamic programming algorithms, but they have the same filling format.
3, Simple example (knapsack problem)
(1) knapsack problem: there is a knapsack with a capacity of 4 pounds, which has the following items
goods | Weight (pounds) | Price ($) |
---|---|---|
Guitar (G) | 1 | 1500 |
Audio (S) | 4 | 3000 |
Computer (L) | 3 | 2000 |
what is the maximum value that can be loaded and put under the capacity? (each item can only be loaded once)
(2) problem solving ideas:
using dynamic programming, the i-th item traversed each time, according to
w
[
i
−
1
]
w[i-1]
w[i − 1] and
v
a
l
[
i
−
1
]
val[i-1]
val[i − 1] to determine whether the item needs to be put into the backpack. That is, for a given n items, set
v
a
l
[
i
−
1
]
val[i-1]
val[i−1],
w
[
i
−
1
]
w[i-1]
w[i − 1] is the value and weight of the ith item respectively (here
i
−
1
i-1
i − 1 is due to the subscript of the array), and M is the capacity of the knapsack. Re order
v
[
i
]
[
j
]
v[i][j]
v[i][j] indicates before
i
i
i items can be loaded with a capacity of
j
j
Maximum value in j's backpack. Then we have the following results:
Step 1: initialize v[i][0]=v[0][i]=0// Indicates that the first row and column of the filled table are 0;
Step 2: when w [i] > J: v[i][j]=v[i-1][j] / / when the capacity of the new product to be added is greater than the capacity of the current backpack, directly use the loading strategy of the previous cell;
Step 3: when J > = w [i]: v[i][j]=max{v[i-1][j], val[i-1]+v[i-1][j-w[i-1]]} / / when the capacity of the new product to be added is less than or equal to the capacity of the current backpack, v[i-1][j]: is the maximum value of the previous cell, val[i-1]: represents the price of the current product, v[i-1][j-w[i-1]]: the optimal solution for loading the i-1 item with the remaining space.
(3) dynamic planning chart:
0 LB | 1 pound | 2 pounds | 3 pounds | 4 pounds | |
---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | |
Guitar (G) | 0 | 1500 | 1500 | 1500 | 1500 |
Audio (S) | 0 | 1500 | 1500 | 1500 | 3000 |
Computer (L) | 0 | 1500 | 1500 | 2000 | 3500 |
(4) code implementation:
package com.haiyang.algorithm.dp; /** * @author haiYang * @create 2022-01-28 16:33 */ public class KnapsackProblem { public static void main(String[] args) { int[] w = new int[]{1, 4, 3};//Article weight int[] val = new int[]{1500, 3000, 2000};//Item price int m = 4;//Backpack Capacity int n = val.length;//Number of items int[][] v = new int[n + 1][m + 1];//Record the maximum value of the first i items that can be loaded into a backpack with a capacity of j int[][] path = new int[n + 1][m + 1]; for (int i = 1; i < v.length; i++) { for (int j = 1; j < v[i].length; j++) { if (w[i - 1] > j) {//w[i-1]: the index of the i-th item array is i-1. When the weight of the i-th item is greater than the capacity of the backpack, it means it can't hold this item, so the maximum value is v[i-1][j] v[i][j] = v[i - 1][j]; } else { //val[i-1] + v[i-1][j-w[i-1]]: indicates the value of the i-1 item plus the maximum value of the remaining space 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[i][j] = 1;//Mark the item and add it to the backpack for easy viewing } 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(); } int i = path.length - 1; int j = path[0].length - 1; //Backtracking output items added to the backpack while (i > 0 && j > 0) { if (path[i][j] == 1) { System.out.println("The first" + i + "Add items to your backpack!"); j = j - w[i - 1]; } i--; } } }