acm.njupt--1882

来源:互联网 发布:公司在线起名软件 编辑:程序博客网 时间:2024/05/05 01:38

C. 数字串划分


时间限制(普通/Java):1000MS/3000MS          运行内存限制:65536KByte
总提交:17            测试通过:6

描述

    给你连续的N个数字符,在其中插入K个乘号将它分成K+1个部分,找出一种分法,使得这K+1个部分的乘积能够为最大。

输入

    程序的输入共有两行:
    第一行是2个正整数N,K(6≤N≤40,1≤K≤6)
    第二行是N个连续的数字符。

输出

    输出所求得的最大乘积(一个自然数)。

样例输入

4  2
1231

样例输出

62

提示

1*2*31=62


分析

动态规划方法。

记F[N][M]表示长为N的序列,划分为M段的最大乘积。

那么F[N][M]=(长为J(J<N)的序列划分为M-1次的值)*(J+1到N组成的数),如下



得到动态规划方程为:


注意事项

1.范围超过int,要用64位int

2.G也是动规生成,计算i-j的数字大小


AC代码

#include<iostream>#define MAX 50using namespace std;__int64 max(__int64 a,__int64 b){    if(a>=b)        return a;    else        return b;}__int64 G[MAX][MAX],dp[MAX][8],str[MAX];int main(){    __int64 n,m,i,j,l;    char ch;    while(scanf("%I64d%I64d",&n,&m)==2)    {        getchar();        for(i=1;i<=n;i++)        {            scanf("%c",&ch);            str[i]=ch-'0';            G[i][i]=str[i];        }        for(i=1;i<=n-1;i++)        {            for(j=i+1;j<=n;j++)            {                G[i][j]=G[i][j-1]*10+str[j];            }        }        for(i=1;i<=n;i++)            dp[i][0]=G[1][i];        for(i=1;i<=n;i++)        {            for(j=1;j<=i;j++)            {                dp[i][j]=0;                for(l=j;l<i;l++)                {                    dp[i][j]=max(dp[i][j],dp[l][j-1]*G[l+1][i]);                }            }        }        printf("%I64d\n",dp[n][m]);    }    return 0;}



2 0