动态规划|最大k乘积问题(C语言)
题目:
【分析】
先通过若干个简单例子来观察规律,摸索思路。例如十进制整数 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语言)相关推荐
- python动态规划算法最大k乘积_C语言使用DP动态规划思想解最大K乘积与乘积最大问题...
最大K乘积问题设I是一个n位十进制整数.如果将I划分为k段,则可得到k个整数.这k个整数的乘积称为I的一个k乘积.试设计一个算法,对于给定的I和k,求出I的最大k乘积. 编程任务: 对于给定的I 和k ...
- 最大k乘积问题---动态规划实验1
问题描述 设I是一个n位十进制整数.如果将I划分为k段,则可得到k个整数.这k个整数的乘积称为I的一个k乘积.试设计一个算法,对于给定的I和k,求出I的最大k乘积. 例如 十进制整数 1234 划分为 ...
- 最大k乘积问题--动态规划
问题 问题描述: 设x是一个n位十进制整数.如果将x划分为k段,则可得到k个整数.这k个整数的乘积称为x的一个k乘积.试设计一个算法,对于给定的x和k,求出x的最大k乘积. 编程任务: 对于给定的x和 ...
- 动态规划之最大K乘积问题
题目要求 设I是一个n位十进制整数.如果将I划分为k段,则可得到k个整数.这k个整数的乘积称为I的一个k乘积.试设计一个算法,对于给定的I和k,求出I的最大k乘积. 例如十进制整数 1234 划分为 ...
- 最大k乘积问题----动态规划
问题 设I是一个n位十进制整数.如果将I划分为k段,则可得到k个整数.这k个整数的乘积称为I的一个k乘积.试设计一个算法,对于给定的I和k,求出I的最大k乘积. 编程任务: 对于给定的I 和k,编程计 ...
- 【动态规划】最大k乘积问题
Description 设I是一个 n位十进制整数.如果将I划分为 k段,则可得到k个整数.这k个整数的 乘积称为I的一个 k乘积.试设计一个算法,对于给定的 I和 k,求出 I的最大 ...
- 【动态规划】最大K乘积问题和游艇租用问题——武汉理工大学算法设计与分析课程实验
1. 最大K乘积问题 « 问题描述 设I是一个n位十进制整数.如果将I划分为k段,则可得到k个整数.这k个整数的乘积称为I的一个k乘积.试设计一个算法,对于给定的I和k,求出I的最大k乘积. 例如十 ...
- PTA 基础编程题目集 7-13 日K蜡烛图 C语言
PTA 基础编程题目集 7-13 日K蜡烛图 C语言 股票价格涨跌趋势,常用蜡烛图技术中的K线图来表示,分为按日的日K线.按周的周K线.按月的月K线等.以日K线为例,每天股票价格从开盘到收盘走完一天, ...
- 动态规划之打家劫舍(House Robber)-C语言实现
动态规划之打家劫舍(House Robber)-C语言实现 前言 打家劫舍是0-1背包经典问题的其中一类,其特征符合经典的动态规划求解流程,通过本经典习题的学习和理解,深入理解0-1经典问题背后的逻辑 ...
最新文章
- scrapy软连接失效和pip软连接失效
- PCB 3D模型与渲染
- Visitor 访问者模式
- ef 排序string转int_Java排序算法——基数排序(Radix Sort)
- jumpserver(0.3.2版本)开源跳板机系统部署
- java 算出下一个工作日,Java:计算一个日期加下指定工作日数(排除周六周日和一系列节日)...
- 看我如何绕过Cloudflare 的 SQL 注入过滤
- 蓝牙模块耳机做蓝牙透传_WiFi、蓝牙在工业领域的数据透传应用_SKYLAB 无线模块...
- bim 水利枢纽 运维_BIM技术与现代化建筑运维管理
- 常用的企业邮箱有哪些?什么邮箱好用
- 人生不设限,要勇于去闯_《不如去闯》读书心得
- 聚焦热门框架、前端架构、工程化……,SDCC 2016前端开发专题讲师、议题大揭底...
- 计算机相关美文摘抄,写景美文摘抄
- 简单易懂的颜色透明度计算
- Discuz X2.0数据字典(数据库表作用解释)
- 如何做好产品经理和如何学习UI
- 1213:八皇后问题1700:八皇后问题
- 一个人最大的本事,是能控制自己的情绪
- 胜不骄 败不馁 心胸似大海宽广
- 使用SSM框架整合时,无法创建XXXXBean
热门文章
- matlab-robtics学习笔记
- 讲讲你不知道的窗口函数
- 运行 ui5 serve 命令行报错的处理方法
- SAP Commerce里Extension, Addon和Accelerator这三个名词的联系和区别
- rxjs里debounceTime operators的用法
- ant build里如何指定classpath
- SAP CRM中间件下载时数据库表CRMATAB为空的处理方法
- 一个最简单的SAP UI5应用部署到SAP云平台CloudFoundry环境后,自动生成了哪些资源
- React应用里Invalid hook call错误消息的处理
- SAP gateway currency transformation from string to ABAP format - deserialization