动态规划法C++实现最大k乘积问题

2023-10-13 00:59

本文主要是介绍动态规划法C++实现最大k乘积问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最大K乘积问题
问题描述
设I是一个n位十进制整数。如果将I划分为k段,则可得到k个整数。这k个整数的乘积称为I的一个k乘积。试设计一个算法,对于给定的I和k,求出I的最大k乘积。
例如十进制整数 1234 划分为 3 段可有如下情形:
1 × 2 × 34 = 68
1 × 23 × 4 = 92
12 × 3 × 4 = 144
编程任务
对于给定的I 和k,编程计算I 的最大k 乘积。
数据输入
输入的第1 行中有2个正整数n和k。正整数n是序列的长度;正整数k是分割的段数。接下来的一行中是一个n位十进制整数。(n<=10)
结果输出
计算出的最大k乘积。
输入文件示例 输出文件示例
input.txt output.txt
3 2
312 62

问题分析
首先用反证法证明最大k乘积问题具有最优子结构性质,从而证明该题目适合使用动态规划法:
(1)假设n位十进制整数I的最大k乘积记为f(n,k),前k-1段总共是m位,且1<=m<n,则最后一段为n-m位,用I(m,n-m)表示从第m位开始的最后n-m位十进制数,则f(n,k)=f(m,k-1)*I(m,n-m).
(2)现在我们假设前面m位十进制整数的最大k-1乘积不是f(m,k-1),而是H(m,k-1),则有H(m,k-1)>f(m,k-1), 左右两边同时乘以I(m,n-m)得H(m,k-1)*I(m,n-m)>f(m,k-1)*I(m,n-m)=f(n,k) 即f(n,k)不是I的最大K乘积与最初的假设相矛盾。
(3)所以f(m,k-1)是前面m位十进制整数的最大k-1乘积,即最大k乘积问题具有最优子结构性质。这说明可以使用动态规划来求解。
算法步骤:
(1)
1.1设tempArr(h,k) 表示: 从第h位到第k位所组成的十进制数
1.2设dp(i,j)表示前i位(1-i)分成j段所得的最大乘积,
1.3arr数组储存给定的n个数字 ;
1.4首先将连续数字第i位到第j位表示的十进制数放在tempArr数组,dp[i][j]代表前i位有j个乘号。
(2)写出动态方程:
如果只分成一段,那么dp[i][1]=tempArr[1][i];
否则: 前i位(1~i)数字分j组乘积的最大值等于分为j-1组的结果再乘以一个后面剩下的数字组成所代表的的十进制数。
dp[i][j]=max(dp[i][j],dp[k][j-1]*tempArr[k+1][i]); 1<=k<i;
(3)最终的结果dp[n][k-1]即为最大k乘积
代码实现:

#include<iostream>
#include <fstream>
#include <string>
#include <sstream>
#include<algorithm>
#include<vector>
#define MAX 20
using namespace std;//数字的位数
int  n = 0;
//分成k段
int k = 0;
//给定的数字
int value = 0;
//存储给定数组的每一个数字
int* arr = NULL;
//存储k乘积最大值
int arr2D[MAX][MAX];
//临时存放第i个到第j个数字表示的十进制数
int tempArr[MAX][MAX];
/*
读取给定的data.txt文件的数据
读取第一行的n , k
第二行的数字 并将每一个数组存储到arr数组中
*/
void readTextData()
{//data.txt为你自己的输入文件路径ifstream ifs("data.txt", ios::in | ios::binary); // 改成你要打开的文件if (ifs.is_open()) {//读取字符的缓冲容器char buf[100];//临时装载读取的元素string s = "";//控制是否读取结束bool fla = false;int count = 0;memset(buf,' ',100);while (!ifs.eof()){//读取文本内容到缓冲容器中ifs.read(buf, 100);for (int i = 0; i < 100; i++) {if (!isspace(buf[i])){//读取遇到空格前的数据,比如" 12 3  4",分别读取为:s="12",s="3",s="4"s += buf[i];}else {if (count  == 0){n = atoi(s.c_str());arr = new int[n];count++;s = "";}else if (count == 1) {k = atoi(s.c_str());count++;s = "";}else if (count == 2){if (buf[i] == '\r' || buf[i] == '\n'){continue;}else{value = atoi(s.c_str());for (int j = 0; j < s.length(); j++){arr[j] = s[j] - 48;}fla = true;break;}}}}if (fla == true){break;}}cout << "输入的数据为:";for (int  i = 0; i < n; i++){cout << arr[i];}cout << endl;ifs.close();}else {cout << "打开文件失败" << endl;}}/*
@to do:将读取到的value从第i个到第j个数字表示的十进制值存储到一个数组中
*/
void init()
{for (int i = 1; i <= n; i++){//给数组对角线赋值tempArr[i][i] = arr[i - 1];}for (int i = 1; i <= n; i++){for (int j = i + 1; j <= n; j++){//获取每个第i到第j位表示的十进制数tempArr[i][j] = tempArr[i][j - 1] * 10 + tempArr[j][j];}}}
int getValue() 
{//枚举前i个数字 for (int i = 1; i <= n; i++)  {//枚举乘号个数  for (int j = 0; j < i; j++){if (j == 0){arr2D[i][j] = tempArr[1][i]; continue;}//枚举乘号位置   for (int k = 1; k < i; k++){//找到最大的k乘积arr2D[i][j] = max(arr2D[i][j], arr2D[k][j - 1] * tempArr[k + 1][i]);}}}//返回最终结果return arr2D[n][k-1];
}int main()
{readTextData();init();int result = getValue();cout <<"最大"<<k<<"乘积结果为:"<< result << endl;system("pause");return 0;
}

当data.txt文件输入为:
在这里插入图片描述
输出结果:
在这里插入图片描述
实验分析:
根据算法我们知道使用了一个一维数组arr,两个二维数组tempArr和dp,所以该算法的空间复杂度为O(nn),在函数init()初始化过程中,使用了两个嵌套的for循环,时间复杂度为O(nn),在getValue()函数中,使用了三个for循环,时间复杂度为O(nnn),所以该算法的时间复杂度为O(nnn)

这篇关于动态规划法C++实现最大k乘积问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/199646

相关文章

Java实现字节字符转bcd编码

《Java实现字节字符转bcd编码》BCD是一种将十进制数字编码为二进制的表示方式,常用于数字显示和存储,本文将介绍如何在Java中实现字节字符转BCD码的过程,需要的小伙伴可以了解下... 目录前言BCD码是什么Java实现字节转bcd编码方法补充总结前言BCD码(Binary-Coded Decima

SpringBoot全局域名替换的实现

《SpringBoot全局域名替换的实现》本文主要介绍了SpringBoot全局域名替换的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录 项目结构⚙️ 配置文件application.yml️ 配置类AppProperties.Ja

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

Python实现批量CSV转Excel的高性能处理方案

《Python实现批量CSV转Excel的高性能处理方案》在日常办公中,我们经常需要将CSV格式的数据转换为Excel文件,本文将介绍一个基于Python的高性能解决方案,感兴趣的小伙伴可以跟随小编一... 目录一、场景需求二、技术方案三、核心代码四、批量处理方案五、性能优化六、使用示例完整代码七、小结一、

Java实现将HTML文件与字符串转换为图片

《Java实现将HTML文件与字符串转换为图片》在Java开发中,我们经常会遇到将HTML内容转换为图片的需求,本文小编就来和大家详细讲讲如何使用FreeSpire.DocforJava库来实现这一功... 目录前言核心实现:html 转图片完整代码场景 1:转换本地 HTML 文件为图片场景 2:转换 H

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

C#使用Spire.Doc for .NET实现HTML转Word的高效方案

《C#使用Spire.Docfor.NET实现HTML转Word的高效方案》在Web开发中,HTML内容的生成与处理是高频需求,然而,当用户需要将HTML页面或动态生成的HTML字符串转换为Wor... 目录引言一、html转Word的典型场景与挑战二、用 Spire.Doc 实现 HTML 转 Word1

C#实现一键批量合并PDF文档

《C#实现一键批量合并PDF文档》这篇文章主要为大家详细介绍了如何使用C#实现一键批量合并PDF文档功能,文中的示例代码简洁易懂,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言效果展示功能实现1、添加文件2、文件分组(书签)3、定义页码范围4、自定义显示5、定义页面尺寸6、PDF批量合并7、其他方法

SpringBoot实现不同接口指定上传文件大小的具体步骤

《SpringBoot实现不同接口指定上传文件大小的具体步骤》:本文主要介绍在SpringBoot中通过自定义注解、AOP拦截和配置文件实现不同接口上传文件大小限制的方法,强调需设置全局阈值远大于... 目录一  springboot实现不同接口指定文件大小1.1 思路说明1.2 工程启动说明二 具体实施2

Vue3绑定props默认值问题

《Vue3绑定props默认值问题》使用Vue3的defineProps配合TypeScript的interface定义props类型,并通过withDefaults设置默认值,使组件能安全访问传入的... 目录前言步骤步骤1:使用 defineProps 定义 Props步骤2:设置默认值总结前言使用T