1. 程式人生 > >經典演算法之動態規劃(一):入門級動態規劃

經典演算法之動態規劃(一):入門級動態規劃

終於要寫高大上的動態規劃啦~~雖然面對高難度的題目還是沒底,但是簡單的可用一維陣列記錄各子問題的解的入門級動態規劃是已經OK的啦~下面以一個鋼條切割的問題為例來講述動態規劃。

假設一公司進了一批長為10的鋼條,打算切割然後去賣,各種長度的鋼條的價格如下表: 

1 2 3 4 5 6 7 8 9 10
1 5 8 9 10 17 17 20 24 25

分析一下:長度為i 的鋼條的價格記為r[i],假設總長度為u 的鋼條經最優方案切割後總價格為price[u],顯然price[10] 即為所求。對於長度為i 的鋼條,其切割的方案有太多種,切一刀,切兩刀……各刀分別切在哪裡等等,這裡我們只考慮第一刀切在哪裡,這樣方案就變成了i 種,而切完第一刀之後剩下的部分,又成了一個和原問題一樣的子問題,假設第一刀切掉了i-u,餘下的部分是u,我們再知道長度為u的鋼條的最優價格就OK了,而由於我們是從小到大開始計算的,當計算price[i]時,price[u] (u<i)早已計算完畢。程式碼如下:

public class CutSteel {

	static int[] r = {0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 25};
	static int[] price = new int[11];
	static int length = 0;//第一刀切在哪裡
	static int[] lengths = new int[11];
	public static void main(String[] args) {
		cut();
		System.out.println(price[10]);
		for(int i=0; i<11; i++){
			System.out.print(lengths[i]+" ");
		}
	}
	private static void cut() {
		price[1] = 1;
		for(int i=2; i<=10; i++){
			int max = r[i];
			length = 0;
			for(int u=1; u<i; u++){
				if(r[i-u]+price[u]>max){
					max = r[i-u]+price[u];
					length = i-u;
				}
			}
			price[i] = max;
			lengths[i] = length;
		}
	}
}


得到的結果是:

27
0 0 0 0 2 3 0 6 6 6 6

lengths[10]=6,也就是說長度為10的鋼條第一刀切掉長度為6的部分,剩下長度為4,而lengths[4]=2,也就是說再切掉長度為2的部分,lengths[2]=0,也就是說不用再切了,於是最優的切割方案是切成6,2,2長的鋼條,可賣得價格27