题目传送门:乘积最大
题意:给一个长度为N的只由数字组成的字符串,往里面添加k个乘号,使得乘积最大,输出这最大乘积。
题解:划分型DP,具体的也不大清楚,没有系统地学习这种DP,但可以清楚知道的是,这个在划分型题目上提供了DP的思路。这题很简单,DP方程:
dp[i][j]=max{strToll(s+i-k, k)*dp[i-k][j-1] }
i表示当前处理的数字串为原始输入的数字串的前i个数字
j表示往这i个数字插入j个乘号
k表示从数字串的末尾分离出一个长度为k的数
s是数字串第一个字符的指针
strToll(char a[], b)表示把数字串a的前b个元素转化为数字
简单地说,就是从字符串末尾分离出一部分作为一个数字,与前面串添加j-1个乘号的结果相乘
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#define ll long long
using namespace std;
ll strToll(char p[], int n)
{
ll sum = 0;
for(char* q = p; q != p+n; ++ q)
sum = sum*10 + (*q-'0');
return sum;
}
ll dp[44][8];
char s[44];
ll DP(int N, int k)
{
if(dp[N][k]) return dp[N][k];
if(k == 0) return dp[N][k] = strToll(s, N);
for(int i = 1; i <= N-k; ++ i)
{
dp[N][k] = max(dp[N][k], strToll(s+N-i, i)*DP(N-i, k-1));
}
return dp[N][k];
}
int main()
{
#ifdef AFei
freopen("in.txt", "r", stdin);
#endif
int N, k;
scanf("%d%d%s", &N, &k, s);
printf("%lld\n", DP(N, k));
return 0;
}
划分型DP的思想让我们在这种划分类型的题目上可以使用DP来解决