题目传送门:乘积最大
题意:给一个长度为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来解决