划分型DP入门(codevs 1017题解)

题目传送门:乘积最大

题意:给一个长度为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来解决

猜你喜欢

转载自blog.csdn.net/q1410136042/article/details/80182220