算法实现题 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;
}