【动态规划】最大k乘积问题

算法实现题 3-15 最大 k 乘积问题
 
问题描述:
设 I 是一个 n 位十进制整数。如果将 I 划分为 k 段,则可得到 k 个整数。这 k 个整数的 乘积称为 I 的一个 k 乘积。试设计一个算法,对于给定的 I 和 k,求出 I 的最大 k 乘积。
 
编程任务:
对于给定的 I 和 k,编程计算 I 的最大 k 乘积。
 
数据输入:
由文件 input.txt 提供输入数据。文件的第 1 行中有 2 个正整数 n 和 k。正整数 n 是序列 的长度;正整数 k 是分割的段数。 接下来的一行中是一个 n 位十进制整数。(n<=10)
 
结果输出:
程序运行结束时,将计算结果输出到文件 output.txt 中。文件的第 1 行中的数是计算出 的最大 k 乘积。
 
输入文件示例
2 1
15

输出文件示例

15

 

m(i,j)——表示第i位到第j位整数组成的(j-i+1)位整数;
dp(p,q)——表示前p位整数被划分为q+1段所得到的最大乘积,即前p个数中间有q个乘号;
[划分段数 > 整数位数,则结果为0]

初始子问题:(q=0时)
       dp(p,0)=m(1,p)
无论多少位整数,被划分为一段,其最大k乘积均为其本身。

下一阶段子问题:(q>=1且q<=p时)
        dp(p,q)=max{dp[p][q],dp(h,q-1)*m(h+1,p)}     (1<=h<=p-1)
p为整数分为q+1段,分别求出前h位这个数分为q段所得最大乘积与余下数段的乘积,选择合适的数据结构记录,然后进行比较,最大的结果即为dp(p,q)。
 


 

#include<bits/stdc++.h>
using namespace std;

int a[101]; 
int m[101][101];//表示第i位到第j位整数组成的(j-i+1)位整数
int dp[101][101];//表示前i位整数被划分为j+1段所得到的最大乘积

int main() {
	int n,k,x;
	cin>>n>>k>>x;
	for(int i=n; i>0; i--) {
		a[i]=x%10;
		x=x/10;
	}
//填补m数组 计算 第i位到第j位组成的j-i+1位整数
	for(int i=1; i<=n; i++)
		m[i][i]=a[i];
		
	for(int i=1; i<=n; i++)
		for(int j=i+1; j<=n; j++)
			m[i][j]=m[i][j-1]*10+m[j][j];
	//枚举数的长度 
	for(int i=1; i<=n; i++) {
		for(int j=0; j<i; j++) {//枚举分段数 
			if(j==0) {//被划分为一段的情况,最大值为其本身 
				dp[i][0]=m[1][i];
				continue;
			}
			for(int p=1; p<i; p++)//以p为界,枚举分割点 
				dp[i][j]=max(dp[i][j],dp[p][j-1]*m[p+1][i]);
		}
	}
	cout<<dp[n][k-1]<<endl;
	return 0;
}

 

 
 
 
 
 
 
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

摆烂.MVP

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值