1. 程式人生 > >ALGO-17 乘積最大(動態規劃)

ALGO-17 乘積最大(動態規劃)

最大乘積 插入 ont return 沒有 主持人 temp 國際 規劃

問題描述

  今年是國際數學聯盟確定的“2000——世界數學年”,又恰逢我國著名數學家華羅庚先生誕辰90周年。在華羅庚先生的家鄉江蘇金壇,組織了一場別開生面的數學智力競賽的活動,你的一個好朋友XZ也有幸得以參加。活動中,主持人給所有參加活動的選手出了這樣一道題目:

  設有一個長度為N的數字串,要求選手使用K個乘號將它分成K+1個部分,找出一種分法,使得這K+1個部分的乘積能夠為最大。

  同時,為了幫助選手能夠正確理解題意,主持人還舉了如下的一個例子:

  有一個數字串:312, 當N=3,K=1時會有以下兩種分法:

  3*12=36
  31*2=62

  這時,符合題目要求的結果是:31*2=62

  現在,請你幫助你的好朋友XZ設計一個程序,求得正確的答案。

入格式

  程序的輸入共有兩行:
  第一行共有2個自然數N,K(6≤N≤40,1≤K≤6)
  第二行是一個長度為N的數字串。


出格式

  輸出所求得的最大乘積(一個自然數)。

  輸入

  4 2
  1231 樣例輸出 62

解題思路:用dp[i][j]存儲前i位插入j個乘號的最大值,狀態轉移方程為 dp[i][j] = max(dp[k][j - 1] * num(k + 1 ~ n));

     外層循環插入的乘號個數,內層循環位數。

     沒有想明白為什麽long long居然在40位1個乘號下不會溢出?

 1 #include<cstdio>
 2 #include<algorithm>
 3
using namespace std; 4 5 long long n[50]; 6 long long dp[50][50]; 7 8 long long get_num(int a, int b){ 9 long long sum = n[a - 1]; 10 for(int i = a; i < b; i++){ 11 sum = sum * 10 + n[i]; 12 } 13 14 return sum; 15 } 16 17 int main(void) 18 { 19 int N, K; 20 scanf("
%d %d", &N, &K); 21 dp[0][0] = 0; 22 int first = 1; 23 for(int i = 0; i < N; i++){ 24 scanf("%1lld", &n[i]); 25 if(first){ 26 first = 0; 27 continue; 28 } 29 dp[i][0] = dp[i -1][0] * 10 + n[i - 1]; 30 } 31 dp[N][0] = dp[N - 1][0] * 10 + n[N - 1]; 32 33 for(int i = 1; i <= K; i++){ 34 for(int j = 1; j <= N; j++){ 35 long long temp = 0; 36 for(int k = i; k < j; k++){ 37 long long kan = get_num(k + 1, j); 38 temp = max(temp, dp[k][i - 1] * get_num(k + 1, j)); 39 } 40 dp[j][i] = temp; 41 } 42 } 43 44 printf("%lld", dp[N][K]); 45 46 return 0; 47 }

ALGO-17 乘積最大(動態規劃)