动态规划 dp05 插入乘号问题 c代码
先看題目:
在一個由n個數字組成的數字串中插入r個乘號(1 <= r < n),將它分成r+1個整數,找出一種乘號的插入方法,使得這r+1個整數的 乘積最大。 例如,對給定的數串267315682902764如何插入6個乘號,使其乘積最大?插入r個乘號是一個多階段決策問題,應用動態規劃來求解。
使用動態規劃需要找到狀態遞推關系,階段自然就是插入的乘號了。
設 f(i, k)表示在前i位數中插入k個乘號所得乘積的最大值,a(i, j)表示從第i位到第j位組成的整數值,先看一個實例:
對給定的的9個數字的數串84731926,如何插入5個乘號,使其乘積最大?
目標是f(9, 5)。
設前8個數字中已插入4個乘號,則最大乘積為f(8,4)* 6
設前7個數字中已插入4個乘號,則最大乘積為f(7,4)* 26
設前6個數字中已插入4個乘號,則最大乘積為f(6,4)* 926
設前5個數字中已插入4個乘號,則最大乘積為f(5,4)* 1926
一般為了求取f(i,k),考察數字串的前i個數字,設在前j (k<= j < i)個數字中已插入k-1個乘號的基礎上,在第j個數字后插入第k個乘號,此時的最大乘積為f(j, k-1)* a(j+1,i)。
由此可得遞推關系式:
f(i, k) = Max( f(j, k - 1) * a(j+1, i) ));
邊界就是當k=0的時候,即插入0個乘號。在遞推的過程中,可以使用額外的c[i][j]數組來記錄乘號插入的位置。
這道題難度中等,思路不容易想到,此外就是編碼的時候容易出錯,需要多多練習。
下面是本題的c代碼實現:
/** n個數插入r個乘號使得乘積最大* f[i][j] 表示前i個數中插入j個乘號的最大值。* f[i][j] = MAX(f[i-k][j-1]*a[i-k+1 ~ i])*/#include <stdio.h> #define MAX(a, b) ((a) > (b) ? (a) : (b))void main() { double f[30][20] = {0}, d;int a[30] = {0}, i, j, k, m, n, r, c[30][20] = {0}, b[20];char l[30];printf("輸入數列:"); scanf("%s",l);printf("輸入插入乘號的個數:"); scanf("%d", &r);n = 0;while(l[n] != '\0'){//字符轉換成數字a[n] = l[n] - 48;n++;}//邊界初始化for (i = 0; i < n - r; i++){for (d = 0, j = 0; j <= i; j++)d = d * 10 + a[j];f[i][0] = d; }//遞推for (j = 1; j <= r; j++){for (i = j; i < n - r + j; i++){for (k = j; k < i; k++){for (d = 0, m = k + 1; m <= i; m++)d = d * 10 + a[m];if (f[i][j] < f[k][j-1] * d){f[i][j] = f[k][j-1] * d;//保存乘號的位置c[i][j] = k;}}}}//打印最優解b[r] = c[n-1][r];for(j = r - 1; j > 0; j--)b[j] = c[b[j+1]][j];for (j = 1, i = 0; j <= r; j++) {while (i <= b[j])printf("%c", l[i++]);printf(" * ");} printf(" = %0.1f\n", f[n-1][r]); }參考資料:
1.?數據結構?: C語言版/ 嚴蔚敏,吳偉民編著
=============================================================================================
Linux應用程序、內核、驅動開發交流討論群(745510310),感興趣的同學可以加群討論、交流、資料查找等,前進的道路上,你不是一個人奧^_^。
?
總結
以上是生活随笔為你收集整理的动态规划 dp05 插入乘号问题 c代码的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 动态规划 dp04 凸n边形的三角形划分
- 下一篇: 递归与递推 普通排队问题及带约束条件的排