乘积最大【DP】

> Description
给出长度为n的一串数字串,要求从中插入k个乘号“*”,算出最大的乘积(0可以作为最高位)。


> Input
第一行输入n与k(6≤N≤40,1≤K≤6)。
第二行输入长度为n的数字串。

> Output
输出最大乘积(一个整数)。


> Sample Input
4 2
1231

> Sample Output
62


> 解题思路
这题输入的数字串中间没有空格隔开,所以只能用字符输入(其实我也不知道,反正我是这样做的),输入时还需处理一下。

f[i][j]表示前i个数字插入j个符号的最大乘积,然后就开始循环插入的符号数t、边界j、与划分k,可以发现:
例如 f[5][3]=max(f[2][1]*s[3][5],f[3][1]*s[4][5],f[4][1]*s[5][5])
也就是前k个数字看做一个整体,用符号数-1个乘号,然后再加上一个乘号,与剩下组成的数相乘,比较算出最大值。

状态转移方程:

f[j][t]=max(f[j][t],f[k][t-1]*s[k+1][j])

感性理解一下
(然后在洛谷上面测用这个方法不开longlong20分,开longlong60分)


> 代码

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
long long f[41][7]={0},ss[41][41];
int n,kk,s[41];
char a;
long long ooo(int x,int y)
{
	if(ss[x][y]!=0) return ss[x][y];
	for(int i=x;i<=y;i++)
	 ss[x][y]=ss[x][y]*10+s[i];
	return ss[x][y];
}//算出剩下的数字组成的数值
int main()
{
	scanf("%d%d\n",&n,&kk);
	for(int i=1;i<=n;i++)
	{
		scanf("%c",&a);
		 s[i]=a-'0';//s存各个位的数字
		f[i][0]=f[i-1][0]*10+s[i];//赋初值:前i个数用0个乘号(=s[1][i])
	}
	for(int t=1;t<=kk;t++)//循环用t个乘号
	 for(int j=t+1;j<=n;j++)//循环前j个数;
	                        //t+1:用t个乘号至少有t+1个数
	  for(int k=t;k<j;k++)//划分界线
	   f[j][t]=max(f[j][t],f[k][t-1]*ooo(k+1,j));
	printf("%lld",f[n][kk]);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值