題目
給一根長度為n的繩子,請把繩子剪成m段(m,n都是整數且1),每段繩子的長度相乘最大乘積是多少?如繩子長度為8,當分別為2,3,3時,此時最大乘積18
思路1
此問題明顯包含獨立的子問題,用f(n)表示長度為n的繩子剪完后的最大乘積,則可以寫出遞推公式
f(n) = max{f(n-i) × f(i)}, 0 < i < n
因為自下而上的時間復雜度為O(n), 每次遞推時要對i循環O(n) ,所以時間復雜度是O(n2)
我們對長度為8的繩子進行模擬。
f(4) = f(2) * f(2) = 4;
f(5) = f(2) * f(3) = 6;
f(6) = f(3) * f(3) = 9;
f(7) = f(3) * f(4) = f(2) * f(5) = 12;
f(8) = f(3) * f(5) = 18;
int maxProAfterCutting(int length){ if (length < 2) return 0; //題目說大於1,因此這是異常輸入 if (length == 2) return 1; if (length == 3) return 2; int* products = new int[length + 1]; products[0] = 0; products[1] = 1; products[2] = 2; products[3] = 3; //其實是從product[4]開始算,這里是為了計算,當輸入0 1 2 3時,前面已經處理 int max = 0; for (int i =4; i <= length; i++){ max = 0; for (int j = 1; j <= i / 2; j++){ int product = products[j] * products[i-j]; if (max < product) max = product; products[i] = max; } } max = products[length]; delete[] products; return max; }
思路2
貪心算法:
當n = 4時,最大乘積就是4.
當n >= 5時,盡可能多剪長度為3的繩子,當剩下為4的時候,就剪成兩段2
也就是說,n>=5時,最大乘積都由若干個3,最多兩個2構成的
證明很簡單:
n >= 5時,3(n-3) >= 2(n-2) > n