首先看一下题意:有一串数字,要求在这串数字中加入k个乘号,使得乘积最大。比如在1231中加入两个乘号,最大的就是。这个题是一道比较基础的动态规划题目,下面说一下我自己的理解。
我们令dp[i][j]表示前i个数中加入j个乘号的最大值,用num[n][m]表示这串数中从n到m的数值,可以提前预处理下。这里我们让乘号递增,让乘号作为最外层循环。那么我们可以得到状态转移方程:,其中k从j开始,一直加到len-1(字符串长度),因为我们每次多加入一个乘号,就意味着要多一个数字,这个数字必然包括最后一个数字,也就是说这个数字的结尾是确定的,就是i,而开头不确定,所以遍历所有可能的开头位置,找出最大的即可。下面贴一下代码,自己最初用long long挂了,后来用了unsigned long long才过。
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
int main(){
ll n,k;
ll num[45][45];
ll dp[45][10];
cin>>n>>k;
string t;
cin>>t;
ll len=t.length();
memset(dp,0,sizeof(dp));
for(int q=0;q<len;q++){
ll tmp=0;
for(int w=q;w<len;w++){
tmp=tmp*10+(t[w]-'0');
num[q][w]=tmp;
}
}
for(int q=0;q<len;q++){
dp[q][0]=num[0][q];
}
for(int q=1;q<=k;q++){
for(int w=q;w<len;w++){
for(int l=q-1;l<len;l++){
dp[w][q]=max(dp[w][q],dp[l][q-1]*num[l+1][w]);
}
}
}
cout<<dp[len-1][k];
return 0;
}