剪繩子

聲明:題目和程序來自《劍指offer》,註釋和分析爲自己所寫備忘,侵刪。

動態規劃

題目:給你一根長度爲n的繩子,請把繩子剪成m段(mn都是整數,n>1並且m>1),每段繩子的長度記爲k[0],k[1],,k[m]。請問k[0] x k[1] xx k[m]可能的最大乘積是多少?例如,當繩子的長度是8時,我們把它剪成長度分別爲2, 3, 3的三段,此時得到的最大乘積是18

分析:動態規劃,POJ上有好多這種題,主要是考慮能否將大問題可以化爲幾個小問題的集合,一般是化爲兩個小問題。在能夠劃分成小問題之後,再考慮是否需要存儲劃分的路徑,怎麼存儲,是否需要存儲小問題的解以加快計算速度等。

對於這個題,f(n) = max( f(i) x f(n-i)), 0<i<n

貪婪算法:不同於動態規劃的遍歷,貪婪每一步都求出對於當前步最優的解,不需要考慮前一步和後一步。貪婪算法的對最優解得判斷是由數學方式計算的。

動態規劃解題思路:

int maxProductAfterCutting_solution(int length)

{

if(length <2)//長度最小爲2

return 0;

if(length ==2)

return 1;//長度等於2的解

if(lentgh ==3)

return 2;//長度等於3的解

int* products = new int[length + 1];//存放最優解得矩陣

products[0] = 0;

products[1] = 1;

products[2] = 1;

products[3] = 2;

 

int max = 0;

for(int i=4;i <=length; i++){//從4開始求最大值,這裏沒有在劃分m的條件下,也沒有存儲最大的劃分方式,只是單單求最大值。

max = 0;

for(j = 1; j<=i/2; j++){

int temp = products[j] *products[i-j];

if(max <temp)

max = temp;

products[i] = max;

}//求products[i]的最大值

}

max = products[length];

delete[] products;

return max;

}

 

貪婪算法代碼:

(當繩子長度>=5時,儘可能多的剪長度爲3的繩子,當剩下長度爲4時,將繩子剪爲兩段長度爲2的繩子)

int maxProductAfterCutting(int length)

{

if(length<2)

return 0;

if(length == 2)

return 1;

if(length == 3)

return 2;

int timesOf3 = length/3;

if(length - timesOf3 * 3 ==1)//剩餘長度爲4時,剪成2x2的

timeOf3 -= 1;

int timeOf2 = (length -timesOf3*3)/2;

return (int)(pow(3, timesOf3))*(int)(pow(2, timesOf2));

}

貪婪算法依據:

繩長n>=5時,2n - 2> n,且3n - 3> n,且3n - 3> 2n - 2)。在f(n) = f(i)*f(n - i)的情況下,分成3n-3的乘積最大。爲什麼這樣分?在n>7時分成4n - 4)不更大嗎?或者5(n - 5),並不是,5(n-5)可以比2*3(n-5)小,4n - 4)等同於2*2n-4),其他6(n-6)同理。至於這個公式怎麼想到的,在考慮動態規劃時,想到劃分1n - 1)、2n - 2)、3n - 3)、4n - 4)、5n - 5),但是從4開始都可以拆爲2,3組合,且2,3組合大於單個數字,根據f(n) = f(i)*f(n-i),考慮將所有的化爲2,3 組合。

這種前提下是沒有限定劃分段數m,僅求最大數,若段數m限定,可以根據


直接求解。

 

 

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章