`
come_for_dream
  • 浏览: 120794 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

最大K乘积

阅读更多

最大K乘积的问题:

在一个长度为N的数字串中插入K-1个乘号,将N分成K部分,找出一种分法,使得这K个部分的最大乘积最大。

例如有一个数字串:312,当N=3,K=2时会有以下几种分法:

3*12=36   31*2=62

但是符合题目的是31*2=62,通过这个例子很明显的可以看出最大k乘积的问题,就是求一个数,将其分成k段,求出段相乘的最大值问题。

 

要求解此问题要用到动态规划的思想,在这里要用到两个数据来分别表示不同的含义

w(h1,h2)表示第h1位到第h2位所组成的十进制数(h2.>h1)

m(i,j)表示:前i位(从1.......N)分成j段所得的最大乘积,则可得到如下的DP方程

if(j==1)   m(i,1)=w(1,i);

if(j>=1&&j<k)

  m(i,j)=max{ m(d,j-1)*w(d+1,i)(1<d<i) }

else if(i<j)   m(i,j)=0;

 

这是一个动态规划的式子。

 

这里是java实现的主要代码:

/**
	 * 对得到的数组进行处理,得到最大K乘积
	 */
	private void maxValue() {

		int size = num.length;
		
		/**
		 *  先把value[i][j]初始化,其代表的是从i开始到j所代表的的整数i<j
		 */
		for (int i = 0; i < size; i++) {
			value[i][i] = num[i];
			for (int j = i + 1; j < size; j++) {
				value[i][j] = value[i][j - 1] * 10 + num[j];
			}
		}

		
		/**
		 * 初始化maxValue第一列,即前i+1位,分成1段所得的最大乘积
		 * 初始化bit第一行和第一列,即当前i+1位分成1段时最后一个乘号的位置,和第一位分成i+1段时最后一个乘号出现的位置,都将他们的初始化为零
		 */
		for (int i = 0; i < size; i++) {
			maxValue[i][0] = value[0][i];
			bit[0][i] = 0;
			bit[i][0] = 0;
		}

		// 关键代码得maxValue[i][j]的值,即前i+1位分成j+1段时的最大乘积(因为下表从零开始)
		for (int i = 1; i < size; i++) {
			//分成二段到intDuan段
			for (int j = 1; j < intDuan; j++) {
				int max = 0;
				int index = 0;
				/**
				 * 找出从前1位到前i-1位分成j-1段时的值与后面的值相乘得到的最大值
				 * 公式:m(i,j)=max{m(d,j-1)*w(d+1,i)}  (1<d<i)
				 */
				for (int k = 0; k < i; k++) {
					if (maxValue[k][j - 1] * value[k + 1][i] > max) {
						max = maxValue[k][j - 1] * value[k + 1][i];
						index = k + 1;
					}
				}
				//得到最大的乘积时,最后一个乘号的位置
				bit[i][j] = index;
				maxValue[i][j] = max;
			}
		}
}

 

 

 

 

全部的代码:

 

package 动态规划;

import javax.swing.JOptionPane;

/**
 * 求最大K乘积
 * 
 * @author ZDX
 * 
 */
public class MaxK {

	int[] num;
	int[][] value;
	// 用来记录最大k乘积
	int[][] maxValue;
	// 用来存储用户输入的分成的分数
	int intDuan;
	// 用来记录乘号最后出现的位置
	int[][] bit;

	int result;

	public MaxK() {
		// 得到要处理的字符串
		String strNum = "";
		while (strNum == null || strNum.equals("")) {
			strNum = JOptionPane.showInputDialog(null, "请输入要进行分解的整数");

		}
		// 将字符串转化为字节数组
		byte[] bt = strNum.getBytes();
		// 初始化
		num = new int[bt.length];
		value = new int[bt.length][bt.length];
		maxValue = new int[bt.length][bt.length];
		bit = new int[bt.length][bt.length];
		// 将得到的字节数组转化为整数数组
		for (int i = 0; i < bt.length; i++) {
			num[i] = bt[i] - 48;
		}

		strNum = "";
		while (strNum == null || strNum.equals("")) {
			strNum = JOptionPane.showInputDialog(null, "请输入要分成的段数:");
		}

		intDuan = Integer.parseInt(strNum);
		maxValue();
	}

	/**
	 * 对得到的数组进行处理,得到最大K乘积
	 */
	private void maxValue() {

		int size = num.length;
		
		/**
		 *  先把value[i][j]初始化,其代表的是从i开始到j所代表的的整数i<j
		 */
		for (int i = 0; i < size; i++) {
			value[i][i] = num[i];
			for (int j = i + 1; j < size; j++) {
				value[i][j] = value[i][j - 1] * 10 + num[j];
			}
		}

		
		/**
		 * 初始化maxValue第一列,即前i+1位,分成1段所得的最大乘积
		 * 初始化bit第一行和第一列,即当前i+1位分成1段时最后一个乘号的位置,和第一位分成i+1段时最后一个乘号出现的位置,都将他们的初始化为零
		 */
		for (int i = 0; i < size; i++) {
			maxValue[i][0] = value[0][i];
			bit[0][i] = 0;
			bit[i][0] = 0;
		}

		// 关键代码得maxValue[i][j]的值,即前i+1位分成j+1段时的最大乘积(因为下表从零开始)
		for (int i = 1; i < size; i++) {
			//分成二段到intDuan段
			for (int j = 1; j < intDuan; j++) {
				int max = 0;
				int index = 0;
				/**
				 * 找出从前1位到前i-1位分成j-1段时的值与后面的值相乘得到的最大值
				 * 公式:m(i,j)=max{m(d,j-1)*w(d+1,i)}  (1<d<i)
				 */
				for (int k = 0; k < i; k++) {
					if (maxValue[k][j - 1] * value[k + 1][i] > max) {
						max = maxValue[k][j - 1] * value[k + 1][i];
						index = k + 1;
					}
				}
				//得到最大的乘积时,最后一个乘号的位置
				bit[i][j] = index;
				maxValue[i][j] = max;
			}
		}

		
        /**
         * 输出将前i位分成j段时所得到的最大值maxValue[i][j]一一输出
         * result最终得到的是该数分成intDuan段相乘的最大值
         */	
		for (int i = 0; i < size; i++) {
			for (int j = 0; j < intDuan; j++) {
				System.out.print(maxValue[i][j] + "   ");
				result = maxValue[i][j];
			}
			System.out.println();
		}

		/**
		 * 输出将前i位分成j段相乘的最大值时最后一个乘号的位置
		 */
		for (int i = 0; i < size; i++) {
			for (int j = 0; j < intDuan; j++) {
				System.out.print(bit[i][j] + "   ");
			}
			System.out.println();
		}

		/**
		 * 得到最终的相乘形式,例:23*41
		 */
		String strOutput = "";
		int i = size - 1;
		int j = intDuan - 1;
		while (j > 0) {
			System.out.println(bit[i][j]);
			
			strOutput = "*" + value[bit[i][j]][i] + strOutput;
			/**
			 * value[bit[i][j]][i]表示的是从最后一个乘号到最后一位的值。这是一个迭代的过程,
			 * 当下一次时原本的数据会将value[bit[i][j]][i]从启辰上去除,再进行处理
			 * 例:数据2341,分成三(j=2,j从0开始计数)段,则最大相乘形式为2*3*41,最后一位的下表(从零开始)i=3后一个乘号出现的位置是bit[i][j]=2,则value[bit[i][j]][i]=41,
			 * 则下次对其进行处理的时候是23,剩下的是将其分成两段(j=1),则i=1,即i=bit[i][j]-1;
			 */

			i = bit[i][j] - 1;
			
			j--;
		}
		//将最前面的一个数字加到字符串上
		strOutput = value[0][i] + strOutput;
		
		JOptionPane.showMessageDialog(null, "最大" + intDuan + "乘积为:" + result
				+ "\n相乘格式为: " + strOutput, "结果", 1);

	}


	public static void main(String[] args) {
		new MaxK();
	}
}

 测试如下:
 

 


 

  • 大小: 12.4 KB
  • 大小: 12.6 KB
  • 大小: 12.3 KB
分享到:
评论

相关推荐

    最大k乘积问题

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

    算法设计实验-最大k乘积问题

    算法设计实验-最大k乘积问题 亲自用Dev-C++测试实验结果,没有任何问题!

    算法-最大K乘积问题

    "最大K乘积问题"是一个典型的算法问题,它涉及到从一组数值中找出前K个乘积最大的元素。这个问题在数据分析、机器学习以及优化问题中都有广泛应用。 首先,我们要理解问题的核心:给定一个整数数组nums和一个正整数...

    算法最大K乘积

    C++实现从input.txt读取k值n值以及数据,计算最大k乘积,并将结果写入文件output.txt,压缩包包含文件readme.txt对代码做了简要介绍,将文件路径修改便可运行,如果想对算法深入了解可查看我的博客:...

    实现3-13最大k乘积问题.cpp

    实现3-13最大k乘积问题.cpp

    C语言使用DP动态规划思想解最大K乘积与乘积最大问题

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

    动态规划经典问题算法:合唱队行,最大k乘积,0-1背包问题,最长上升子序列,田忌赛马,花瓶插花

    下面,我们将讨论动态规划经典问题算法,包括合唱队行、最大 k 乘积、0-1 背包问题、最长上升子序列、田忌赛马、花瓶插花等。 一、合唱队行 合唱队行是动态规划经典问题之一。该问题可以描述为:有 n 个人站在一排...

    整数字符串分隔成k段后每段乘起来最大乘积

    将一个整数字符串用*分隔成k段后,将每段数字相乘得到的最大乘机

    动态规划k乘积问题.doc

    输出结果则写入output.txt,只包含计算出的最大k乘积。 对于测试,我们可以设计不同规模的输入数据,例如一个5位数分成3段,以及一个6位数分成6段的情况,验证算法的正确性和效率。通过这样的实验,可以深入理解和...

    自然数最优分解乘积最大的严格数学证明.pdf

    文章也提到了一个关键的函数P(k),这个函数利用了h(k)和h(k+1)来界定n的范围,这个范围内的n分解后会得到一个最大的乘积。P(k)函数在不同条件下有不同的结果,这些结果都是通过对条件进行分析和计算得到的。 文章...

    第3章动态规划实验.zip

    在本实验中,我们将深入探讨动态规划这一重要的算法思想,主要涵盖了五个具体的问题:最大k乘积问题、独立任务最优调度问题、最小m段和问题、字符串比较问题以及石子合并问题。动态规划是一种用于解决最优化问题的...

    四川大学算法设计报告

    四川大学的这份算法设计报告详细诠释了这两种算法的应用,特别是在整数因子分解和最大k乘积问题中的运用。 在探讨整数因子分解问题时,报告指出了递归算法的核心思想:将一个大问题分解为若干个小问题,通过递归...

    算法设计(实验一、二).zip

    本篇将围绕武汉理工大学算法设计课程的两个实验进行深入探讨,分别是实验一中的分治法应用——中位数计算和Gray码生成,以及实验二中的动态规划策略——最大k乘积问题和游艇最少租金问题。这些实验旨在让学生理解和...

    算法能力训练题 典型算法

    在这个主题下,我们可以看到几个典型的问题,包括最大子矩阵问题、整数划分问题和最大K乘积问题。下面我们将逐一深入探讨这些算法问题。 1. **最大子矩阵和问题**: 这个问题要求在给定的m行n列整数矩阵中找到一个...

    乘积图的分数染色 (2008年)

    引理2.1表明对于两个图G和H,其乘积图G×H的分数色数是G和H的分数色数的最大值。定理2.2进一步说明了如果G的分数色数等于其色数,且H的色数不超过G的分数色数,则乘积图G×H的分数色数与G的分数色数相等。 ### 知识...

    回溯法采用的搜索策略-五大常用算法——回溯算法详解及经典例题,算法数据结构

    另一个例子是最大k乘积问题,该问题要求将一个整数分成k段,并求出这k段组成的整数的最大乘积。通过回溯法,我们可以尝试不同的分割方式,每次分割后计算乘积,然后回溯以尝试其他可能的分割,最终找到最大乘积。 ...

    规划问题的程序例子.zip

    接着,"最大k乘积"问题是一个寻找数组中k个元素乘积最大的情况。这里,我们需要考虑到如何有效地更新当前的最大乘积,同时保持k个元素的集合。动态规划可以通过维护两个有序集合(最大值和最小值),在每一步中找到...

    最大m段乘积和最小m段和

    根据给定文件的信息,我们可以深入探讨“最大m段乘积和最小m段和”的核心概念与算法实现。这个主题涉及到动态规划(Dynamic Programming)在数组处理中的应用,具体目标是找到一个数组中最大m段的乘积以及最小m段的...

    C++课程设计乘积最大样本.doc

    通过遍历所有可能的插入位置和乘号数量,更新f[i][j]的值,并最终得到整个数字串插入K个乘号的最大乘积p(1, n, k)。 解题的关键在于,对于每个j(1≤j≤k),我们需要找到一个位置q,将数字串分为前后两部分,使得...

Global site tag (gtag.js) - Google Analytics