1275:【例9.19】乘积最大

题目链接

题意简述

设有一个长度为N的数字串,要求选手使用K个乘号将它分成K+1个部分,找出一种分法,使得这K+1个部分的乘积最大。

同时,为了帮助选手能够正确理解题意,主持人还举了如下的一个例子:

有一个数字串:312, 当N=3,K=1时会有以下两种分法:

  • 3*12=36

  • 31*2=62

这时,符合题目要求的结果是:31*2=62。

现在,请你帮助你的好朋友XZ设计一个程序,求得正确的答案。

样例

点击查看样例

分析

本题探讨的是一个序列在区间上的性质,因此用区间DP
最外层枚举用的乘号的个数
dp[i][k]表示前i个数字中使用k个乘号
然后求前k+1,k+2,...,n的序列用k个乘号所能得到的最大值
其中对于前 i 个字符的序列,用 m 个乘号相乘时,只需先列出来前 m,m+1,...,i1 (记为j ) 个字符的序列用 m1 个乘号的最大值,然后第 m 个乘号的位置就是在第 j 个字符后.
其最大值的求法是先得到前m,m+1,...,i1个字符用m1个乘号的最大值 dp[j][m1] ,然后乘以 a[j+1][i] . 取max 即可.
dp[i][k]=max(dp[i][k],dp[j][k1]num[j+1][i])

预处理:
a[i...j]表示了str[i...j]组成的数字
dp[i][0]即前i个字符用0个乘号得到的结果,自然是a[1][i]

代码

点击查看代码
#include<stdio.h>
#include<iostream>
#include<cstdlib>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=20;
LL a[N][N];
LL dp[N][N];
char s[N];
int main()
{
	//freopen("uva.txt","r",stdin);
	int n,k;
	scanf("%d%d",&n,&k);
	scanf("%s",s+1);
	for(int i = 1;i <= n;i++)
	{
		a[i][i] = s[i]-'0';
	}
	for(int i = 1;i <= n;i++)
	{
		LL t = a[i][i];
		for(int j = i+1;j<=n;j++)
		{
			a[i][j] = t*10 + a[j][j];
			t = a[i][j];
		//	printf("%d %d %lld\n",i,j,a[i][j]);
		}
	}
	for(int i = 1;i <= n;i++)dp[i][0] = a[1][i];
	
	for(int m = 1;m <= k ;m ++)
	{
		for(int i = m + 1;i <= n ;i++)
		{
			for(int j = m ;j < i ;j++)
			{
				dp[i][m] = max(dp[i][m],dp[j][m-1]*a[j+1][i]); 
			}
		}
	}
	printf("%lld\n",dp[n][k]);
	return 0;
}



如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
posted @   Rainy_L  阅读(434)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示