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问题通常都不止一种考虑方式,上述方法仅为作者个人想法,记之与诸位共勉。
也请各位读者发散思维,自行仔细思考,或许会想出更好的解法。

浙公网安备 33010602011771号