动态规划法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

相关文章

Python实现终端清屏的几种方式详解

《Python实现终端清屏的几种方式详解》在使用Python进行终端交互式编程时,我们经常需要清空当前终端屏幕的内容,本文为大家整理了几种常见的实现方法,有需要的小伙伴可以参考下... 目录方法一:使用 `os` 模块调用系统命令方法二:使用 `subprocess` 模块执行命令方法三:打印多个换行符模拟

SpringBoot+EasyPOI轻松实现Excel和Word导出PDF

《SpringBoot+EasyPOI轻松实现Excel和Word导出PDF》在企业级开发中,将Excel和Word文档导出为PDF是常见需求,本文将结合​​EasyPOI和​​Aspose系列工具实... 目录一、环境准备与依赖配置1.1 方案选型1.2 依赖配置(商业库方案)二、Excel 导出 PDF

Python实现MQTT通信的示例代码

《Python实现MQTT通信的示例代码》本文主要介绍了Python实现MQTT通信的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 安装paho-mqtt库‌2. 搭建MQTT代理服务器(Broker)‌‌3. pytho

Spring的RedisTemplate的json反序列泛型丢失问题解决

《Spring的RedisTemplate的json反序列泛型丢失问题解决》本文主要介绍了SpringRedisTemplate中使用JSON序列化时泛型信息丢失的问题及其提出三种解决方案,可以根据性... 目录背景解决方案方案一方案二方案三总结背景在使用RedisTemplate操作redis时我们针对

使用zip4j实现Java中的ZIP文件加密压缩的操作方法

《使用zip4j实现Java中的ZIP文件加密压缩的操作方法》本文介绍如何通过Maven集成zip4j1.3.2库创建带密码保护的ZIP文件,涵盖依赖配置、代码示例及加密原理,确保数据安全性,感兴趣的... 目录1. zip4j库介绍和版本1.1 zip4j库概述1.2 zip4j的版本演变1.3 zip4

Kotlin Map映射转换问题小结

《KotlinMap映射转换问题小结》文章介绍了Kotlin集合转换的多种方法,包括map(一对一转换)、mapIndexed(带索引)、mapNotNull(过滤null)、mapKeys/map... 目录Kotlin 集合转换:map、mapIndexed、mapNotNull、mapKeys、map

nginx中端口无权限的问题解决

《nginx中端口无权限的问题解决》当Nginx日志报错bind()to80failed(13:Permissiondenied)时,这通常是由于权限不足导致Nginx无法绑定到80端口,下面就来... 目录一、问题原因分析二、解决方案1. 以 root 权限运行 Nginx(不推荐)2. 为 Nginx

python生成随机唯一id的几种实现方法

《python生成随机唯一id的几种实现方法》在Python中生成随机唯一ID有多种方法,根据不同的需求场景可以选择最适合的方案,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习... 目录方法 1:使用 UUID 模块(推荐)方法 2:使用 Secrets 模块(安全敏感场景)方法

解决1093 - You can‘t specify target table报错问题及原因分析

《解决1093-Youcan‘tspecifytargettable报错问题及原因分析》MySQL1093错误因UPDATE/DELETE语句的FROM子句直接引用目标表或嵌套子查询导致,... 目录报js错原因分析具体原因解决办法方法一:使用临时表方法二:使用JOIN方法三:使用EXISTS示例总结报错原

Windows环境下解决Matplotlib中文字体显示问题的详细教程

《Windows环境下解决Matplotlib中文字体显示问题的详细教程》本文详细介绍了在Windows下解决Matplotlib中文显示问题的方法,包括安装字体、更新缓存、配置文件设置及编码調整,并... 目录引言问题分析解决方案详解1. 检查系统已安装字体2. 手动添加中文字体(以SimHei为例)步骤