DP——最大乘积问题

题意简述

  设有一个长度N的数字串,要求使用K个乘号将它分成K+1个部分,找出一种分法,使得这K+1个部分的乘积能够为最大。 

问题分析

  显然是一个DP问题。

  下面详述本人解题思路:

  记该数字串为a.

  状态表示:f[i,j]表示将a1~ai分成j个部分的所有方案中的最大乘积.

  状态计算:

    考虑所分成的最后一个部分的左端边界(右端必然为ai),记为ak,1<=k<=i.

    f[i,j] = max{ f[k-1 , j-1] * w[k , i] }

    w[k , i]表示ak~ai所有数字所组成的数.

    w[i , j] = w[i , j-1] * 10 + aj

  考虑边界:当仅分成一个部分时,f[i , 1] = w[1 , i].

  时间复杂度:O(n3)

参考代码

 

#include <cstdio>
#include <algorithm>
using namespace std;

const int N=110;

int n,s;
int a[N];
int w[N][N];
int f[N][N];

int main()
{
    scanf("%d%d",&n,&s);
    for(int i=1;i<=n;i++)scanf("%1d",&a[i]);
    
    for(int i=1;i<=n;i++)
        for(int j=i;j<=n;j++)
            w[i][j]=w[i][j-1]*10+a[j];
    
    for(int i=1;i<=n;i++)f[i][1]=w[1][i];
    
    for(int j=2;j<=s+1;j++)
        for(int i=1;i<=n;i++)
            for(int k=1;k<=i;k++)
            f[i][j]=max(f[i][j],f[k-1][j-1]*w[k][i]);
    
    printf("%d\n",f[n][s+1]);
    return 0;
} 

 

写在最后

 

  一个DP问题通常都不止一种考虑方式,上述方法仅为作者个人想法,记之与诸位共勉。

  也请各位读者发散思维,自行仔细思考,或许会想出更好的解法。

posted @ 2019-12-20 21:15  魑吻丶殇之玖梦  阅读(133)  评论(0)    收藏  举报