acm.njupt--1882

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组成的数),如下

acm.njupt--1882_第1张图片


得到动态规划方程为:


注意事项

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

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


AC代码

#include<iostream>
#define MAX 50
using 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;
}



你可能感兴趣的:(ACM,njupt,1882)