第九章 動態規劃-1275:【例9.19】乘積最大

1275:【例9.19】乘積最大

時間限制: 1000 ms 內存限制: 65536 KB

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

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

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

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

1)3*12=36

2)31*2=62

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

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

【輸入】
第一行共有2個自然數N,K(6≤N≤10,1≤K≤6)

第二行是一個長度爲N的數字串。

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

【輸入樣例】
4 2
1231
【輸出樣例】
62


思路:本道題是一道區間DP問題,而且對階段數有限制 k。可以將其按照插入乘號數來進行劃分。如果插入k個乘號,可以把問題看做k個階段的決策問題。
階段、狀態、決策三層循環。
在考慮加一個乘號的時候要考慮這個乘號應該放在當前面有k-1的乘號時,後面的哪個位置比較好。也就是說要確定前j位用k個乘號f[i][k](j>=k+1)的結果,應該從 有k-1個乘號的各種方案(前幾位中已經包括了k-1個乘號)中選擇哪種方案將第k個乘號加在後面之後結果最大。
有k個乘號時,數字至少要有k+1位。有k-1個乘號時,數字至少要有k位。
狀態轉移方程:f[i][k] = max ( f[i][k], f[j][k-1] * num[j+1][i] )(j < i)

#include <iostream>
#include <cstdio>
#include <cstring>
#define INF 0x3f3f3f3f
#define N 500
using namespace std;

int maxx[N][N], num[N][N];
char number[N];
int n, k;
int main() {
	scanf("%d%d", &n, &k);
	getchar();
	scanf("%s", number);
	for(int i = 0; i < n; i++) {
		num[i+1][i+1] = number[i] - '0';
	}
	for(int j = 2; j <= n; j++) {
		for(int i = j-1; i >= 1; i--) {
			num[i][j] = num[i][j-1] * 10 + num[j][j];
		}
	}
	for(int i = 1; i <= n; i++) {
		maxx[i][0] = num[1][i];
	}
	for(int l = 1; l <= k; l++) {
		for(int i = l+1; i <= n; i++) {
			for(int j = l; j <= i-1; j++) {
				maxx[i][l] = max(maxx[i][l], maxx[j][l-1] * num[j+1][i]);
			}
		}
	}
	printf("%d\n", maxx[n][k]);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章