题目:

【分析】
先通过若干个简单例子来观察规律,摸索思路。例如十进制整数 1234 划分为 3 段可有如下情形:
1 × 2 × 34 = 68
1 × 23 × 4 = 92
12 × 3 × 4 = 144(满足要求的解)

以计算正整数 1234 的最大 3 乘积为例,即 I = 1234,n = 4,k = 3(将 1234 分为 3 段)。由于计算乘积时要使用整数中的“一段”数字,则定义 w(s,t) 表示 I 中从第 s 位到第 t 位组成的数,如 w(2,3)=23;按照动态规划算法处理问题的步骤,定义 m(i,j) 表示整数 I 的前 i 位分成 j 段所得的“最大 j 乘积”,显然所求的问题即为计算 m(n,k)。
根据上述定义,显然有:
(1)当 i < j 时(这种情况下整数 I 的前 i 位无法分成 j 段),定义 m(i,j) = 0;
(2)当 j = 1 时(分为 1 段),有 m(i,j) = m(i,1) = w(1,i);
(3)当 j > 1且 j <= i 时,从 I 中的前 d 位数字(d 从 1 循环到i-1)可得到“最大 j-1 乘积(即 j-1 分段)”,然后乘以剩下的数字(组成 1 段,为 w(d+1,i),即从 d+1 位开始,到 I 的第 i 位),写成状态方程即为:

计算过程中会建立 2 个二维数组 W 和 M,前者是 n x n 阵,储存w(s,t) 的值(表示 I 中从第 s 位到第 t 位组成的数);后者是 n x k 阵,储存 m(i,j) 的值 。以计算正整数 1234 的最大 3 乘积为例,即 I = 1234,n = 4,k = 3,则有:

综上,可得m(i,j)的递推关系如下:

代码:

// 使用的库定义
#include <stdio.h>
#include <stdlib.h>
#include <string.h>// ######################################################################## //
//                                                                          //
//                              下面是数据定义区                               //
//                                                                          //
// ######################################################################## //#define STR_LEN 100
#define TRUE    1
#define FALSE   0//// ######################################################################## //
//                                                                          //
//                           下面是各个子函数定义                               //
//                                                                          //
// ######################################################################## //int  CalcMaxKProduct( int n, int k, int **D, int **P );  //计算正整数的最大 k 乘积
void PrintProductMatrix( int n, int k, int **D, int **P );//显示计算数据 //// ######################################################################## //
//                                                                          //
//                          下面是各个子函数的实现                             //
//                                                                          //
// ######################################################################## //// 使用动态规划法计算两个字符串之间的编辑距离 ...
//
// 测试数据如下 :
// ( 1 ) 1234 划分为 3 段 : 12 * 3 * 4 = 144
// ( 2 ) 自行设计 2 个测试用例
int CalcMaxKProduct( int n, int k, int **D, int **P )
{int i, j, t, maxv, tk;//当i<j无法进行分段 for(i = 1;i <= n;i++)  //分成一段 j=1 {P[i][1]= D[1][i];}for(i = 1; i <= n;i++)  //DP过程 {for(j = 2;j <= i;j++)   //当 j > 1且 j <= i 时,从 I 中的前 t 位数字(t 从 1 循环到i-1)可得到“最大 j-1 乘积(即 j-1 分段) {maxv = 0;for(t = 1;t < i;t++){if((tk = P[t][j-1]*D[t+1][i]) > maxv)  //然后乘以剩下的数字(组成 1 段,为 D(t+1,i),即从 t+1 位开始,到 I 的第 i 位), maxv = tk;}P[i][j] = maxv;}}return P[n][k];
}// 打印编辑距离矩阵 ...
void PrintProductMatrix( int n, int k, int **D, int **P )
{int i, j;// 打印 'D' ...printf( "\t生成的整数分段值矩阵为 : \n" );for(i=1 ; i<= n; i++){for(j=1 ; j<= n; j++){printf("%d ",D[i][j]);printf(" ");} printf("\n");}printf( "\n\n" );// 打印 'P' ...printf( "\t生成的分段乘积矩阵为 : \n" );for(i=1 ; i<= n; i++){for(j=1 ; j<= k; j++){printf("%d ",P[i][j]);printf(" ");}printf("\n");
}printf( "\n\n" );
}//// ######################################################################## //
//                                                                          //
//                             下面是主程序的实现                              //
//                                                                          //
// ######################################################################## //int main()
{char StrI[ STR_LEN ];char StrK[ STR_LEN ];int  *I, n;    // 储存输入的整数及其长度 ...int  k;        // 输入的整数分为 'k' 段 ...int  **D, **P; // 二维数组, 储存整数的各个分段值及乘积值 ...int  i, j, MaxProduct;int  IsStop;IsStop = FALSE;while ( !IsStop ){// 清屏 ...system( "cls" );// 输入整数 'I' ...printf( "\n\n\t请输入 < 整数 I 的值 > , 输入 < q / Q > 表示结束 : " );scanf( "%s", StrI );n = strlen( StrI ); // 输入整数的位数 ...if ( n > 0 )IsStop = ( ( StrI[ 0 ] == 'q' ) || ( StrI[ 0 ] == 'Q' ) );elseprintf( "\t输入的整数不能为空 !\n\n" );if ( !IsStop ){// 输入分段数 'k' ...printf( "\n\t请输入 < 整数分段数 k > , 输入 < q / Q > 表示结束 : " );scanf( "%s", StrK );if ( strlen( StrK ) > 0 )IsStop = ( ( StrK[ 0 ] == 'q' ) || ( StrK[ 0 ] == 'Q' ) );elseprintf( "\t输入的整数分段数不能为空 !\n\n" );// 输入的整数及其分段数 'I' 和 'k' 均不为空, 则计算最大 'k' 乘积 ...if ( !IsStop ){// 将输入的字符串转换为整数 ...// 输入的整数 'I' ...// 动态申请一维数组 ...I = ( int * )malloc( ( n + 1 ) * sizeof( int ) );// 将输入的字符串整数的每一位放入 'I' 中 ...for ( i = 1; i <= n; i++ )I[ i ] = StrI[ i - 1 ] - '0'; // 注意序号起始值 ...// 输入的分段数 'k' ...k = atoi( StrK ); //把StrK(字符串)转换为一个整数 // 动态申请二维数组 'D' 和 'P' ...// 'D' - 储存整数的各个分段值( n x n 阵 ) ...//定义 D(s,t) 表示 I 中从第 s 位到第 t 位组成的数 D = ( int ** )malloc( ( n + 1 ) * sizeof( int ) );for ( i = 0; i <= n; i++ )D[ i ] = ( int * )malloc( ( n + 1 ) * sizeof( int ) );// 初始化 ...for ( i = 0; i <= n; i++ )for ( j = 0; j <= n; j++ )D[ i ][ j ] = 0;// 'P' - 储存整数的分段乘积值( n x k 阵 ) ...//定义 P(i,j) 表示整数 I 的前 i 位分成 j 段所得的“最大 j 乘积” P = ( int ** )malloc( ( n + 1 ) * sizeof( int ) );for ( i = 0; i <= n; i++ )P[ i ] = ( int * )malloc( ( k + 1 ) * sizeof( int ) );// 初始化 ...for ( i = 0; i <= n; i++ )for ( j = 0; j <= k; j++ )P[ i ][ j ] = 0;// 生成 'D' 矩阵 ...//表示 I 中从第 s 位到第 t 位组成的数 for( i = 1 ;i <= n; i++ ){D[i][i] = I[i];for(j = i+1;j <= n;j++){D[i][j] = D[i][j-1]*10+I[j];   }}// 计算最大 'k' 乘积 ...MaxProduct = CalcMaxKProduct( n, k, D, P );// 显示计算结果 ...printf( "\n\t< 计算得到的最大 k 乘积为:%d > \n\n", MaxProduct );// 打印数值矩阵 ...PrintProductMatrix( n, k, D, P );// 释放二维数组 'D' 和 'P' 的空间 ...for ( i = 0; i <= n; i++ )free( D[ i ] );free( D );for ( i = 0; i <= n; i++ )free( P[ i ] );free( P );// 等待用户输入任意一键返回 ...printf( "\n\n" );system( "PAUSE" );}}}// 等待用户输入任意一键返回 ...printf( "\n\n" );return 0;
}//

运行结果:

动态规划|最大k乘积问题(C语言)相关推荐

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

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

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

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

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

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

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

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

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

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

  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. PTA 基础编程题目集 7-13 日K蜡烛图 C语言

    PTA 基础编程题目集 7-13 日K蜡烛图 C语言 股票价格涨跌趋势,常用蜡烛图技术中的K线图来表示,分为按日的日K线.按周的周K线.按月的月K线等.以日K线为例,每天股票价格从开盘到收盘走完一天, ...

  9. 动态规划之打家劫舍(House Robber)-C语言实现

    动态规划之打家劫舍(House Robber)-C语言实现 前言 打家劫舍是0-1背包经典问题的其中一类,其特征符合经典的动态规划求解流程,通过本经典习题的学习和理解,深入理解0-1经典问题背后的逻辑 ...

最新文章

  1. scrapy软连接失效和pip软连接失效
  2. PCB 3D模型与渲染
  3. Visitor 访问者模式
  4. ef 排序string转int_Java排序算法——基数排序(Radix Sort)
  5. jumpserver(0.3.2版本)开源跳板机系统部署
  6. java 算出下一个工作日,Java:计算一个日期加下指定工作日数(排除周六周日和一系列节日)...
  7. 看我如何绕过Cloudflare 的 SQL 注入过滤
  8. 蓝牙模块耳机做蓝牙透传_WiFi、蓝牙在工业领域的数据透传应用_SKYLAB 无线模块...
  9. bim 水利枢纽 运维_BIM技术与现代化建筑运维管理
  10. 常用的企业邮箱有哪些?什么邮箱好用
  11. 人生不设限,要勇于去闯_《不如去闯》读书心得
  12. 聚焦热门框架、前端架构、工程化……,SDCC 2016前端开发专题讲师、议题大揭底...
  13. 计算机相关美文摘抄,写景美文摘抄
  14. 简单易懂的颜色透明度计算
  15. Discuz X2.0数据字典(数据库表作用解释)
  16. 如何做好产品经理和如何学习UI
  17. 1213:八皇后问题1700:八皇后问题
  18. 一个人最大的本事,是能控制自己的情绪
  19. 胜不骄 败不馁 心胸似大海宽广
  20. 使用SSM框架整合时,无法创建XXXXBean

热门文章

  1. matlab-robtics学习笔记
  2. 讲讲你不知道的窗口函数
  3. 运行 ui5 serve 命令行报错的处理方法
  4. SAP Commerce里Extension, Addon和Accelerator这三个名词的联系和区别
  5. rxjs里debounceTime operators的用法
  6. ant build里如何指定classpath
  7. SAP CRM中间件下载时数据库表CRMATAB为空的处理方法
  8. 一个最简单的SAP UI5应用部署到SAP云平台CloudFoundry环境后,自动生成了哪些资源
  9. React应用里Invalid hook call错误消息的处理
  10. SAP gateway currency transformation from string to ABAP format - deserialization