乘积最大(区间dp)

 今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年。在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一个好朋友XZ也有幸得以参加。活动中,主持人给所有参加活动的选手出了这样一道题目:
设有一个长度N的数字串,要求选手使用K个乘号将它分成K+1个部分,找出一种分法,使得这K+1个部分的乘积能够为最大。

分析:

设dp[i][j]为前i个数字插入j个乘号所得最大值
sum[i][j]为从i到j数字串所代表的数字
则dp[i][j] = max(dp[k][j - 1] * sum[k + 1][i]);
#include<bits/stdc++.h>
#define pi acos(-1.0)
#define maxn (100 + 5)
#define mol 1000000007
#define inf 50000
#define Lowbit(x) (x & (-x))
using namespace std;
typedef long long int LLI;
char str[maxn];
int sum[maxn][maxn],dp[maxn][maxn];
int main() {
//	freopen("in.txt", "r", stdin);
//	freopen("out.txt", "w", stdout);
    int n,k;
    scanf("%d%d",&n,&k);
    scanf("%s",str);
    for(int i = 0; i < n; i ++) {
        sum[i][i] = str[i] - '0';
        for(int j = i + 1; j < n; j ++)
            sum[i][j] = sum[i][j - 1] * 10 + str[j] - '0';//求出i-j间数字;
    }
    for(int i = 0; i < n; i ++) {
        dp[i][0] = sum[0][i];
        for(int j = 1; j <= min(i,k); j ++) {
            for(int k1 = 0; k1 < i; k1 ++)
                dp[i][j] = max(dp[i][j],dp[k1][j - 1] * sum[k1 + 1][i]);
        }
    }
    printf("%d\n",dp[n - 1][k]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lanshan1111/article/details/81783446