问题

问题描述:
设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{1
234,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;//返回字符串中所截取到的数
}int main()
{int n,k;//初始条件输入 cout<<"请输入整数位数n:";cin>>n;cout<<"请输入整数划分位数k:";cin>>k;        //n位数被分为k段cout<<"请输入"<<n<<"位整数x:";cin>>x;        //输入的数int f[n+1][k+1];//f[i][j]: 数字的前i位数被分为j段所得到的最大乘积  1/2/34int i,j,h;int t[k];//建立划分点 int c[n][k];//初始化 for(i=1;i<=n;i++)//表示是第一列的内容,数只分为一段,于是这部分的数就是当前内容{for(j=1;j<=k;j++){f[i][j]=0;}**f[i][1]=num(1,i);//边界条件** }//这段 j=1 是不将数字分段,就是前i位数//num(1,i)是指截取从第0位到第i-1位的数 //(1234:f[1][1]=1,f[2][1]=12,f[3][1]=123,f[4][1]=1234)for(j=2;j<=k;j++)//分为j段{for(i=j;i<=n;i++)//前i位数 {for(h=j-1;h<i;h++)//h为划分点,这是在对前面i个数进行划分,这也只是划分点数的位置,并非是数 {//f[h][j-1]*num(h+1,i)=前h个数被分为j-1段最大的乘积 *第j段的数(也就是没有并入前h个数的i-h个数) if(f[i][j]<f[h][j-1]*num(h+1,i))//这里是在判断前面 {**f[i][j]=f[h][j-1]*num(h+1,i)**;//记录当前位置的最大值 **c[i][j-1]=h;** //记录当前求出最大值的断点位置,也就是插入乘号的位置,这个位置是数    }}} }t[k-1]=c[n][k-1];//记录当前倒数第一个断点位置 for(j=k-2;j>=1;j--)//逆推出第j个乘号的位置t[j] {**t[j]=c[t[j+1]][j];**//这是在利用后一个断点位置找出前一个断点位置 }t[0]=0;//t数组没有插入断点,此处赋值是为了后面输出结果 t[k]=n;//t数组的k位没有插入断点,此处赋值是为了后面输出结果 cout<<endl;cout<<"划分过程乘积最优子结果内容如下(打表):"<<endl;cout<<"i\\j\t";for(int z=1;z<=k;z++){cout<<z<<"\t";} cout<<endl;for(i=1;i<=n;i++)//输出打表内容,求出最优解 {cout<<" "<<i<<"\t";for(j=1;j<=k;j++){cout<<f[i][j]<<"\t";}cout<<endl;}    cout<<endl;cout<<x<<"分成"<<k<<"段后的最大k乘积是:";for(j=1;j<=k;j++)//输出最优值的分割内容 {   **for(int u=t[j-1]+1;u<=t[j];u++)**//输出从一个断点到另一个断点中间的数 {cout<<x[u-1]; }if(j<k)//输出乘号做分割 {cout<<"*";}}//输出最优值 cout<<"="<<f[n][k]<<endl;
}`

输出结果测试:


添加:
(由于本人是编程小白第一次写blog,文章内容有些优化不足。并且该解法只能解决较简单的最大k乘积问题,不能解决较长的数据,等待更深入的学习后,作者会添加更优的解法,如果有其他大佬有更好的解法欢迎分享!)

最大k乘积问题--动态规划相关推荐

  1. 最大k乘积问题---动态规划实验1

    问题描述 设I是一个n位十进制整数.如果将I划分为k段,则可得到k个整数.这k个整数的乘积称为I的一个k乘积.试设计一个算法,对于给定的I和k,求出I的最大k乘积. 例如 十进制整数 1234 划分为 ...

  2. 最大k乘积问题----动态规划

    问题 设I是一个n位十进制整数.如果将I划分为k段,则可得到k个整数.这k个整数的乘积称为I的一个k乘积.试设计一个算法,对于给定的I和k,求出I的最大k乘积. 编程任务: 对于给定的I 和k,编程计 ...

  3. 动态规划|最大k乘积问题(C语言)

    题目: [分析] 先通过若干个简单例子来观察规律,摸索思路.例如十进制整数 1234 划分为 3 段可有如下情形: 1 × 2 × 34 = 68 1 × 23 × 4 = 92 12 × 3 × 4 ...

  4. python动态规划算法最大k乘积_C语言使用DP动态规划思想解最大K乘积与乘积最大问题...

    最大K乘积问题设I是一个n位十进制整数.如果将I划分为k段,则可得到k个整数.这k个整数的乘积称为I的一个k乘积.试设计一个算法,对于给定的I和k,求出I的最大k乘积. 编程任务: 对于给定的I 和k ...

  5. 动态规划之最大K乘积问题

    题目要求 设I是一个n位十进制整数.如果将I划分为k段,则可得到k个整数.这k个整数的乘积称为I的一个k乘积.试设计一个算法,对于给定的I和k,求出I的最大k乘积. 例如十进制整数 1234 划分为 ...

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

    Description         设I是一个 n位十进制整数.如果将I划分为 k段,则可得到k个整数.这k个整数的 乘积称为I的一个 k乘积.试设计一个算法,对于给定的 I和 k,求出 I的最大 ...

  7. 【动态规划】最大K乘积问题和游艇租用问题——武汉理工大学算法设计与分析课程实验

    1.  最大K乘积问题 « 问题描述 设I是一个n位十进制整数.如果将I划分为k段,则可得到k个整数.这k个整数的乘积称为I的一个k乘积.试设计一个算法,对于给定的I和k,求出I的最大k乘积. 例如十 ...

  8. python动态规划算法最大k乘积_划分类动态规划——乘积最大(洛谷1018,codevs1017)...

    本题由于比较老,数据实际也比较小,用long long 即可通过 代码: var n,m,i,j,k,sum:longint; s,t:string; a:array[1..40,1..40] of ...

  9. 蓝桥杯 算法训练 乘积最大(动态规划)

    问题描述 今年是国际数学联盟确定的"2000--世界数学年",又恰逢我国著名数学家华罗庚先生诞辰90周年.在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一 ...

最新文章

  1. RewriteCond和13个mod_rewrite应用举例Apache伪静态
  2. python数据结构视频百度云盘_数据结构与算法Python视频领课
  3. 写一个 JavaScript 框架:比 setTimeout 更棒的定时执行
  4. 递归——阶乘加斐波那契数列(简单掌握递归思想的敲门砖)
  5. Ubuntu安装常用软件
  6. linux如何加入windows域
  7. 游戏开发之初识C++模板(C++基础)
  8. linux可视化界面改ip,Linux图形界面模式更改ip地址
  9. ecshop shopex_json.php,Shopex到ECShop的转换教程
  10. 百科知识 kux文件如何打开
  11. 南卡和声阔蓝牙耳机哪个比较好用?降噪效果好的蓝牙耳机推荐
  12. Re-ranking Person Re-identification with k-reciprocal Encoding笔记
  13. MATLAB制图代码
  14. C语言ALG什么文件,alg.exe进程是什么
  15. 苹果手机可以微信分身吗_微信和微信分身版有区别吗
  16. k8s添加pod,k8常用命令,k8s删除pod
  17. unable to create jaxbcontext 最终解决办法
  18. SSL数字证书之CA根证书、CA中间证书和SSL证书
  19. ElasticSerach 6.0.1 测试IK分词器和拼音分词器是否生效
  20. 李开复谈苹果、微软、Google的优点和弱点是什么?

热门文章

  1. 抖音黑客帝国代码雨——程序大神如何攻占抖音?简直不可思议!
  2. 没有显卡怎么使用anaconda配置tensorflow深度学习环境
  3. 电子商务网站SEO推广策略
  4. JSON中的optString和getString的区别
  5. 如何实现扫描条码自动打印标签?
  6. zhs16gbk mysql_Oracle 11g 修改字符集 为 ZHS16GBK
  7. 【Android】23、如何知晓当前是在哪一个活动
  8. 无限镜面灯板制作教程
  9. Arduino编程-步进电机角度控制
  10. 离心泵水力设计——蜗壳设计