乘积最大【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])

感性理解一下


> 代码

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,kk,s[41],f[41][7]={0};
char a;
int ooo(int x,int y)
{
	int ans=0;
	for(int i=x;i<=y;i++)
	 ans=ans*10+s[i];
	return ans;
}//算出剩下的数字组成的数值
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("%d",f[n][kk]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43010386/article/details/84889479