Initial Dynamic Programming: how to skillfully resolve to scrape together a single problem "double October" shopping?

Initial Dynamic Programming: how to skillfully resolve to scrape together a single problem "double October" shopping?

Taobao "double October" shopping festival promotional activities, such as "full 200 by 50", if there is something you want to buy n-girlfriend shopping cart, pick and choose a few, full reduction under the premise lobbied conditions in so elected to maximize the sum of the reduction in commodity prices near full condition

Dynamic route planning study

Dynamic programming is more suitable for solving optimization problems, such as seeking maximum, minimum

Section I: two classical models of dynamic programming problem, we need to show dynamic programming, dynamic programming and problem-solving methods Why is how evolution out

Section II: Summary of dynamic programming for problem-solving features, dynamic programming and problem-solving ideas

Section III: classic dynamic programming to solve real problems

0-1 knapsack problem

//回溯算法实现。注意:把输入的变量都定义成了成员变量
private int maxW = Integer.MIN.VALUE;  //结果放到maxW中
private int[] weight = {2,3,4,6,3}  //物品重量
private int n = 5 ;//物品个数
private int w = 9 ;//背包承受的最大重量
public void f(int i , int cw){  //调用f(0,0)
	if(cw == w || i == n){   //cw == w 表示装满了,i == n表示物品都考察完了
		if(cw > maxW) maxW = cw ;
		return;
	}
	f(i+1,cw);  //选择不装第i个物品
	if(cw + weight[i] <= w){
		f(i+1,cw + weight[i]);  //选择装第i个物品
	}
}

Suppose backpack maximum load weight is 9, there are five different items, namely 2,2,4,6,3, an example of the solution process by backtracking recursive tree drawn, it is:

​ f(0,0)

​ f(1,0) f(1,2)

​ f(2,0) f(2,2) f(2,2) f(2,4)

​ f(3,0) f(3,4) f(3,2) f(3,6) f(3,2) f(3,6) f(3,4) f(3,8)

Each node in the tree recursively represented by one state (i, cw) denotes, i denotes the number of items for making a decision whether or not into the backpack, the backpack CW represents the total weight of the current, such as (2,2) to be represented Decision two items are loaded backpack, before the decision, the total weight of the backpack is article 2,

Recursive tree, some issues were double-counted twice, that can make use of recursive section of the "memorandum" addressed several of the records and calculate f (i, cw), avoid redundancy

private int maxW = Integer.MIN_VALUE;  //结果放到maxW中
private int[]  weight = {2,2,4,6,3} ;   //物品重量
private int n = 5 ;//物品个数
private int w = 9;//背包承受的最大重量
private boolean[][] mem = new boolean[5][10];  //备忘录,默认值是false
public void f(int i , int cw){  //调用f(0,0)
	if(cw == w || i == n){   //cw == w表示装满了,i == n表示物品都考察完了
		if(cw > maxW) maxW = cw;
		return;
	}
	if(mem[i][cw])  return;   //重复状态
	mem[i][cw] = true;   //记录(i,cw)这个状态
	f(i+1,cw) ; //选择不装第i个物品
	if(cw +weight[i] <= w){
		f(i+1,cw +weight[i]);   //选择装第i个物品
	}
}

Then the dynamic programming approach is: the whole solution process is divided into n stages, each stage will be a decision whether the items into the backpack, after each item the decision (or not placed into the backpack) finished, backpack items by weight have many cases, i.e., reach the state of a plurality of different, correspond to a recursive tree, that is, there are many different nodes, the state of each layer of the combined duplicate records only different states, then, based on layer state set, to derive the one set of states. The number can be repeated for each layer of the combined state, the state of each layer are different to ensure that no more than W

States with a two-dimensional array [n][w+1], each record different states can be achieved, by weight of 0 (subscript numbered starting from 0) the article is 2, or into a bag, backpack or not charged, after completion decisions, will correspond to backpack two states, the total weight of the item backpack is 0 or 2, with the States [0][0]= to true and States [0][2]= to true to indicate two states

By weight of an item is 2, based on previous knapsack state, after the article decision completely different states have three, the total weight of the items in a backpack are 0 (0 + 0), 2 (0 + 2 or 2 +0), 4 (2 + 2) States [1][0]= to true, States [1][2]= to true, States [1][4]= to true to indicate three states

And so on, until all items After inspection, the entire array is calculated states, 0 represents false, 1 represents true, one need only find the closest value of true values ​​of w = 9 in the final, total weight of the article is a backpack maximum

weight:物品重量      n:物品个数 , w:背包可承载重量
public int knapsack(int[] weight , int n ,int w){
	boolean[][] states = new boolean[n][w+1];  //默认值false
	states[0][0] = true;   //第一行的数据要特殊处理,可以利用哨兵优化
	if(weight[0] <= w){
		states[0][weight[0]]  = true;
	}
	for(int i = 1; i < n ; ++i){  //动态规划状态转移
		for(int j = 0 ; j <= w ; ++j){   // 不把第i个物品放入背包
			if(states[i -1][j]  == true) states[i][j] = states[i -1][j];
		}
		for(int j = 0 ;j <= w-weight[i] ; ++j){   //把第i个物品放入背包
			if(states[i-1][j]  == true) states[i][j+weight[i]]  =true;
		}
	}
	for(int i = w ; i >= 0 ;--i) {   //输出结果
		if(states[n-1][i]  == true)  return i;
	}
	return 0 ;
}

The problem is divided into a plurality of stages, each stage corresponding to a decision, for each record a set of states reachable stage, then a stage to derive a set of state set by the state of the current phase

Although the efficiency of dynamic programming is relatively high, but the need for additional application n multiplied by a two-dimensional array w + 1 can reduce space consumption it?

Only one size is one-dimensional array w + 1 can solve this problem

public static int knapsack2(int[] items , int n , int w){
	boolean[] states = new boolean[w+1];//默认值false
	states[0] = true;   //第一行的数据要特殊处理,可以利用哨兵优化
	if(items[0] <= w){
		states[items[0]] = true;
	}
	for(int i = 1 ; i < n ; ++i){    //动态规划
		for(int j = w-items[i] ; j >= 0 ; --j){   //把第i个物品放入背包
			if(states[j] == true)  states[j+items[i]] = true;
		}
	}
	for(int i = w ; i >= 0 ; --i){   //输出结果
		if(states[i]  == true) return i ;
	}
	return 0 ;
}

0-1 knapsack problem upgraded version

The value of this variable is introduced items, select certain items into the backpack, the backpack maximum weight limit to meet the premise of, the backpack can be loaded into the total value of goods is the largest number?

The use of backtracking algorithm to solve:

private int maxV = Integer.MIN_VALUE;//结果放到maxV中
private int[] items={2,2,4,6,3}; //物品的重量
private int[] value={3,4,8,9,6};//物品的价值
private int n = 5;//物品个数
private int w = 9 ;//背包承受的最大重量
public void f(int i , int cw,int cv){  //调用f(0,0,0)
	if(cw == w || i == n){//cw == w 表示装满了,i==n表示物品都考察完了
		if(cv > maxV) maxV = cv;
		return;
	}
	f(i+1,cw,cv);  //选择不装第i个物品
	if(cw + weight[i] <= w){
		f(i+1,cw +weight[i],cv+value[i];  //选择装第i个物品)
	}
}

Need three variables (i, cw, cv) to represent a state, i denotes the i-th upcoming decision whether the items into the backpack, cw represents the total weight of the backpack in the current article, cv represents the total value of the current kinds of backpack items

There are few nodes i and cw are identical, (2,2,4) in this state is as follows f (2,2,4) & f (2,2,3), as the total weight of the case, f the total value of goods higher corresponding to discard f (2,2,3), (2,2,4) this decision go along f

Dynamic Programming:

Or the whole solution process is divided into n stages, each stage will be a decision whether the items into the backpack, after completion of each stage of the decision, the total weight and the total value of the items in the backpack, there will be a variety of circumstances, that is, It will reach many different states

States with a two-dimensional array [n][w+1], each to record different states can be achieved, where the array is stored in the current state corresponds to a maximum total value, the each layer (i, cw) merge state is repeated, only the cv values recorded the maximum state, this state is then derived based on the state of the next layer

public static int knapsack3(int[] weight,int[] value,int n ,int w){
	int[][] states = new int[n][w+1];
	for(int i = 0 ; i < n ; ++i){   //初始化states
		for(int j = 0 ; j < w+1;++j){
			states[i][j] = -1;
		}
	}
	states[0][0] = 0;
	if(weight[0] <= w){
		states[0][weight[0]] = value[0];
	}
	for(int i = 1;i < n ;++i){   //动态规划,状态转移
		for(int j = 0 ; j <= w;++j){   //不选择第i个物品
			if(states[i-1][j] >= 0) states[i][j] = states[i-1][j];
		}
		for(int j = 0;j <= w-weight[i] ;++j){   //选择第i个物品
			if(states[i-1][j] >= 0 ){
				int v = states[i-1][j] + value[i];
				if(v > states[i][j+weight[i]]){
					states[i][j+weight[i]] = v;
				}
			}
		}
	}
	
	//找出最大值
	int maxvalue = -1;
	for(int j = 0 ; j <= w ;++j){
		if(states[n-1][j] > maxvalue) maxvalue = states[n-1][j];
	}
	return maxvalue;
}

Pascal's Triangle for some transformation, digital free to fill each position, after a certain number can only reach two numbers adjacent to the layer below, if you move down in the first layer, move to the lowest level passes the sum of all numbers, defined as the length of the path, the program obtains the shortest path length from the bottom to the top moving

​ 5

​ 7 8

​ 2 3 4

​ 4 9 6 1

​ 2 7 9 4 5

int[][] matrix={{5},{7,8},{2,3,4},{4,9,6,1},{2,7,9,4,5}};

public int yanghuiTriangle(int[][] matrix){
	int[][] state = new int[matrix.length][matrix.length];
	state[0][0] = matrix[0][0];
	for(int i = 1 ; i < matrix.length ; i++){
		for(int j =0 ; j < matrix[i].length;j++){
			if(j == 0)  state[i][j] = state[i -1][j] + matrix[i][j;]
			else if(j == matrix[i].length -1)  state[i][j ] = state[i -1][j - 1] + matrix[i][j];
			else{
				int top1 = state[i- 1][j -1];
				int top2 = state[i - 1][j];
				state[i][j] = Math.min(top1,top2) + matrix[i][j];
			}
		}
	}
	
	int minDis = Integer.MAX_VALUE;
	for(int i = 0 ; i < matrix[matrix.length - 1] . length;i++){
		int distance = state[matrix.length -1][i];
		if(distance < minDis)  minDis = distance;
	}
	return minDis;
}

Published 75 original articles · won praise 9 · views 9181

Guess you like

Origin blog.csdn.net/ywangjiyl/article/details/104717901