生活随笔
收集整理的這篇文章主要介紹了
动态规划|最大k乘积问题(C语言)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目:
【分析】
先通過若干個簡單例子來觀察規律,摸索思路。例如十進制整數 1234 劃分為 3 段可有如下情形:
1 × 2 × 34 = 68
1 × 23 × 4 = 92
12 × 3 × 4 = 144(滿足要求的解)
以計算正整數 1234 的最大 3 乘積為例,即 I = 1234,n = 4,k = 3(將 1234 分為 3 段)。由于計算乘積時要使用整數中的“一段”數字,則定義 w(s,t) 表示 I 中從第 s 位到第 t 位組成的數,如 w(2,3)=23;按照動態規劃算法處理問題的步驟,定義 m(i,j) 表示整數 I 的前 i 位分成 j 段所得的“最大 j 乘積”,顯然所求的問題即為計算 m(n,k)。
根據上述定義,顯然有:
(1)當 i < j 時(這種情況下整數 I 的前 i 位無法分成 j 段),定義 m(i,j) = 0;
(2)當 j = 1 時(分為 1 段),有 m(i,j) = m(i,1) = w(1,i);
(3)當 j > 1且 j <= i 時,從 I 中的前 d 位數字(d 從 1 循環到i-1)可得到“最大 j-1 乘積(即 j-1 分段)”,然后乘以剩下的數字(組成 1 段,為 w(d+1,i),即從 d+1 位開始,到 I 的第 i 位),寫成狀態方程即為:
計算過程中會建立 2 個二維數組 W 和 M,前者是 n x n 陣,儲存w(s,t) 的值(表示 I 中從第 s 位到第 t 位組成的數);后者是 n x k 陣,儲存 m(i,j) 的值 。以計算正整數 1234 的最大 3 乘積為例,即 I = 1234,n = 4,k = 3,則有:
綜上,可得m(i,j)的遞推關系如下:
代碼:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STR_LEN 100
#define TRUE 1
#define FALSE 0
int CalcMaxKProduct( int n
, int k
, int **D
, int **P
);
void PrintProductMatrix( int n
, int k
, int **D
, int **P
);
int CalcMaxKProduct( int n
, int k
, int **D
, int **P
)
{int i
, j
, t
, maxv
, tk
;for(i
= 1;i
<= n
;i
++) {P
[i
][1]= D
[1][i
];}for(i
= 1; i
<= n
;i
++) {for(j
= 2;j
<= i
;j
++) {maxv
= 0;for(t
= 1;t
< i
;t
++){if((tk
= P
[t
][j
-1]*D
[t
+1][i
]) > maxv
) maxv
= tk
;}P
[i
][j
] = maxv
;}}return P
[n
][k
];
}
void PrintProductMatrix( int n
, int k
, int **D
, int **P
)
{int i
, j
;printf( "\t生成的整數分段值矩陣為 : \n" );for(i
=1 ; i
<= n
; i
++){for(j
=1 ; j
<= n
; j
++){printf("%d ",D
[i
][j
]);printf(" ");} printf("\n");}printf( "\n\n" );printf( "\t生成的分段乘積矩陣為 : \n" );for(i
=1 ; i
<= n
; i
++){for(j
=1 ; j
<= k
; j
++){printf("%d ",P
[i
][j
]);printf(" ");}printf("\n");
}printf( "\n\n" );
}
int main()
{char StrI
[ STR_LEN
];char StrK
[ STR_LEN
];int *I
, n
; int k
; int **D
, **P
; int i
, j
, MaxProduct
;int IsStop
;IsStop
= FALSE
;while ( !IsStop
){system( "cls" );printf( "\n\n\t請輸入 < 整數 I 的值 > , 輸入 < q / Q > 表示結束 : " );scanf( "%s", StrI
);n
= strlen( StrI
); if ( n
> 0 )IsStop
= ( ( StrI
[ 0 ] == 'q' ) || ( StrI
[ 0 ] == 'Q' ) );elseprintf( "\t輸入的整數不能為空 !\n\n" );if ( !IsStop
){printf( "\n\t請輸入 < 整數分段數 k > , 輸入 < q / Q > 表示結束 : " );scanf( "%s", StrK
);if ( strlen( StrK
) > 0 )IsStop
= ( ( StrK
[ 0 ] == 'q' ) || ( StrK
[ 0 ] == 'Q' ) );elseprintf( "\t輸入的整數分段數不能為空 !\n\n" );if ( !IsStop
){I
= ( int * )malloc( ( n
+ 1 ) * sizeof( int ) );for ( i
= 1; i
<= n
; i
++ )I
[ i
] = StrI
[ i
- 1 ] - '0'; k
= atoi( StrK
); D
= ( int ** )malloc( ( n
+ 1 ) * sizeof( int ) );for ( i
= 0; i
<= n
; i
++ )D
[ i
] = ( int * )malloc( ( n
+ 1 ) * sizeof( int ) );for ( i
= 0; i
<= n
; i
++ )for ( j
= 0; j
<= n
; j
++ )D
[ i
][ j
] = 0;P
= ( int ** )malloc( ( n
+ 1 ) * sizeof( int ) );for ( i
= 0; i
<= n
; i
++ )P
[ i
] = ( int * )malloc( ( k
+ 1 ) * sizeof( int ) );for ( i
= 0; i
<= n
; i
++ )for ( j
= 0; j
<= k
; j
++ )P
[ i
][ j
] = 0;for( i
= 1 ;i
<= n
; i
++ ){D
[i
][i
] = I
[i
];for(j
= i
+1;j
<= n
;j
++){D
[i
][j
] = D
[i
][j
-1]*10+I
[j
]; }}MaxProduct
= CalcMaxKProduct( n
, k
, D
, P
);printf( "\n\t< 計算得到的最大 k 乘積為:%d > \n\n", MaxProduct
);PrintProductMatrix( n
, k
, D
, P
);for ( i
= 0; i
<= n
; i
++ )free( D
[ i
] );free( D
);for ( i
= 0; i
<= n
; i
++ )free( P
[ i
] );free( P
);printf( "\n\n" );system( "PAUSE" );}}}printf( "\n\n" );return 0;
}
運行結果:
總結
以上是生活随笔為你收集整理的动态规划|最大k乘积问题(C语言)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。