问题
问题描述:
设x是一个n位十进制整数。如果将x划分为k段,则可得到k个整数。这k个整数的乘积称为x的一个k乘积。试设计一个算法,对于给定的x和k,求出x的最大k乘积。
编程任务:
对于给定的x和k,编程计算x的最大k 乘积。
示例
Sample Input:
请输入整数位数n:4
请输入整数划分位数k:3
请输入4位整数x:1234
Sample Output:
1234的k-1次分割后的最大k乘积是:144
推导过程
将一个n位的数字划分为k段,注意到分为k段是一个多阶段决策测问题,应采用动态规划算法来求解是适宜的。
推导打表过程:
(假设输入4位整数1234划分为3段求最大乘积数)
第一列:表示整数只分一段,结果就是本身。
第二列:表示整数分为两段。
f(2,2)=max{f(1,1)num(1,2)}= max{12}=2;
f(3,2)=max{f(1,1)num(2,3),f(2,1)num(3,3)}=max{123,123}=36;
f(4,2)=max{f(1,1)num(2,3),f(2,1)num(3,4),f(3,1)num(4,4)}=
max{1234,1234,1234}=492;
第三列:表示整数分三段。
f(3,3)=max{f(2,2)num(3,3)}=max{123}=6;
f(4,3)=max{f(2,2)num(3,4),f(3,2)num(4,4)}=max{1234,364}=144;
状态转移方程:
f(i,j):表示前i个数分为j段后的最大乘积数。num(i,j)表示第i位开始到第j位的数。一般为了求取f(i,j),求数前i位,设前h个数中已经分成了j-1段,此时最大乘积为(h,j-1)*num(j+1,i)。f(i,j)=max{f(h,j-1)*num(j+1,i)} (j-1<=h<=i-1)
边界条件:
前面i个数字没有进行划分是值显然为前i个数字组成的整数,因而得到边界值为:
f(i,1)=num(1,i) (1<=i<=n)
打印结果乘号:
为了能够打印相应的插入乘号的乘积式,设置标注位置的数组t[j]和c[i][j],其中c[i][j]是为了相应的f[i][j]的第j-1个划分点的位置,而t[j]表明了第j-1个乘号的位置。
当给数组赋值f[i][j]=f[h][j-1]*num(h+1,i)时,做相应赋值c[i][j-1]=h,表明f[i][j]的第j-1个乘号的位置时h。在求得f[n][k]时第k-1个乘号的位置t[k-1]=c[n][k-1]=h的基础上,其他tj可应用t[j]=c[t[j+1]][j]逆推产生。
具体案例实现流程
利用notability实现推导6位数字765438划分为4段求解最大乘积问题
代码实现:
c++代码:(重点代码有标注**–**)
`#include<iostream>
#include<string>
using namespace std;
string x;//全局变量
int num(int i,int j)//是为了截取从i开始的长度为j的数字
{
int sum=0;
for(int k=i;k<=j;k++)//将字符串转换为相对应的数,如字符串123->数123
{
**sum=sum*10+(x[k-1]-'0');**
}
return sum;//返回字符串中所截取到的数