0/1 Knapsack Classic Example Introduction to Dynamic Programming

  When the author participated in the online written test of Meituan, I encountered a topic related to dynamic programming. Unfortunately, the author at that time was very immature and knew nothing about algorithms. So, with the attitude of studying, when I was planning to get started with dynamic programming, I found this classic Dynamic programming ( Dynamic Programming, DP ) introductory question - 0/1 knapsack problem, after reading the solutions of the great gods, I simply worship, so I plan to implement it manually and pay tribute to the big guys. Hereby, an excerpt.

  The so-called 0/1 means that the items loaded into the backpack have only two states (loaded and not loaded). OK, not much nonsense, the question:

topic:

条件:
* 一个背包,最大容量12Kg
* 5个物品,分别的重量为1 , 3 , 2 , 6 , 2(单位都是Kg),分别的价值为2 , 5 , 3 , 10 , 4(这个单位任意)
问题:
* 求背包最多能装下多少价值的物品?

  OK, let's talk about the solution to the problem:

  1. Confirm the sub-problems and state 01 The knapsack problem needs to be solved, in order to maximize the total value of the objects in the knapsack of volume V, should the ith item of N items be put into the knapsack? (In which each item can only be placed at most one) To this end, we define a two-dimensional array, in which each element represents a state, that is, several of the first i objects are placed in a volume with the largest value in the V backpack. The array is: f[N][V], where fij represents the maximum value of several items in the first i pieces put into the knapsack of volume j.
  2. The initial state The initial state is f[0][0−V] and f[0−N][0] are both 0, the former means that the total value of the first 0 items (that is, empty items) is the same no matter how big the package is. It is 0, the latter means that a backpack with a volume of 0 cannot fit any valuable items.
  3. transfer function
if (背包体积j小于物品i的体积)
    f[i][j] = f[i-1][j] //背包装不下第i个物体,目前只能靠前i-1个物体装包
else
    f[i][j] = max(f[i-1][j], f[i-1][j-Vi] + Wi)

  The meaning of the last sentence is based on "In order to maximize the total value of the objects in the knapsack of volume V, should the ith item of N items be put into the knapsack?" Vi represents the volume of the ith object, and Wi represents the value of the ith item. In this way, f[i-1][j] represents not putting this item into the backpack, and f[i-1][j-Vi] + Wi represents the total value after putting the i-th item into the backpack , compare the values ​​of the two, and get the largest value and store it in the current backpack.

OK, here's the code I wrote myself:

package package_0_1;

/**
 * 0/1 背包问题
 * @author xiao
 *
 */
public class Package01 { 
	// 背包的最大重量
	public static int package_weight_max = 12;
	// 一共有几种物品
	public static int Total_Item = 5;
	// 每种物品的价值
	public static int[] values= {0 , 2 , 5 , 3 , 10 , 4};
	// 每种物品的重量
	public static int[] Items_Weight = {0 , 1 , 3 , 2 , 6 , 2};
	/* 一个二维数组,用来表示从前i个物品里
	 * 选出最合适的装进载重量为j背包中,使
	 * 得背包里的价值最大。i∈Items j∈{0-package_weight_max}
	 * dp[i][j] 单位是 (价值)
	*/
	public static int dp[][] = new int[Total_Item+1][package_weight_max+1];
	
	/**
	 * 初始化dp二维数组
	 */
	public static void initialize_dp() {
		for(int[] i : dp) {
			for(int j :i) {
				j=0;
			}
		}
	}
	
	/**
	 * DP 计算递推矩阵(求出每个局部最优解,将其保存进二维数组,方便递推)
	 */
	public static int DPMethod() {
		initialize_dp();
		
		// 构造二维数组
		for(int i = 1;i<=Total_Item;i++) {
			for(int j = 1;j<=package_weight_max;j++) {
				/* 如果背包容量小于物品的重量,则不放入此物品,
				 * 将放入上一物品的最大价值作为这次的最大价值
				 */
				if(j<Items_Weight[i]) {
					dp[i][j] = dp[i-1][j];
				}
				/* 如果背包容量足够放下这件物品,那么就
				 * 比较不放入物品时的最大价值与放入此物
				 * 品时的最大价值谁大,将大的作为这次的最大价值
				 */
				else {
					// GetMax(不放入物品的价值,此物品的价值+剩余空间的最大价值)
					dp[i][j] = GetMax(dp[i-1][j],(dp[i-1][j-Items_Weight[i]]+values[i]));
				}
				System.out.print(dp[i][j]+" ");
			}
			System.out.println("");
		}
		// 至此求得解
		return dp[Total_Item][package_weight_max];
	}
	
	/**
	 * 求最大值
	 * @param i
	 * @param j
	 * @return
	 */
	private static int GetMax(int i, int j) {
		// TODO Auto-generated method stub
		if(i>j) {
			return i;
		}else {
			return j;
		}
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println("计算矩阵如下: ");
		int result = DPMethod();
		System.out.println(String.format("12kg背包最多能装进价值为 %d 的物品", result));
	}

}

OK, record this first!

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325140152&siteId=291194637