`
ql213
  • 浏览: 11463 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

动态规划之最大乘积问题

阅读更多

    求解动态规划问题的核心在于找准阶段与阶段之间的状态变化规律,从而制定状态转化的决策,由上一阶段的所有局部最优状态值推出下一阶段的局部最优,进而推出全局最优。 在求解问题的时候,我们通常要构造一个二维数组,用来保存当前得到的局部最优值,这样在推导下一阶段的最优值的时候就可以利用上一阶段得到的结果求解,而这显然比穷举更高效。 记住动态规划的一个思想:许多当前的局部最优看不见未来的最优,但是未来的最优一定包含当前的某个局部最优。


以某年的信息学竞赛为例,题目大意如下:
在一个长为N的数字字符串s中插入r个乘号,将s拆分成r+1部分,求其最大乘积。

思路:
该题目可以用动态规划的思想求解,因为s的最大乘积可以由局部最大乘积得到。如果我们把该题的阶段定义为插入乘号的个数,那么阶段1就是插入第1个乘号,阶段二就是插入第2个乘号,...,阶段r就是插入第r个乘号。

而每个阶段的状态则对应插入乘号的位置。另外,每个阶段的取值集合由该阶段的乘号数目决定。例如,阶段1对应的字符串长度显然应该大于1,阶段r对应的字符串长度应该大于r+1。

有了阶段的制定,进一步分析得到其状态转化的决策:

我们设阶段i的状态是f[i,k],其中i是目前数字字符串的结尾,即s.sub(0,i),k是待插入的第k个乘号。基于前面提到得到未来的最优一定包含当前的某个局部最优,这里的未来就是f[i,k].它的最优值必定从当前已得到的最优解集合{f[j,k-1]}(其中k<=j<r)得到。{f[j,k-1]}表示数字字符串s.sub(0,j)中插入k-1个乘号的最大值。

经过分析,状态转移公式如下:

f[i,k]=max{f[[j][k-1]*Int(s.substring(j,i))} 其中(j>=k&&j<i)

有了状态转移公式,那么编程就比较容易了。

 

Java代码

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MaxMultiplication {
	
	/**
	 * 在一个长为N的数字串中插入r个乘号,将它拆分成r+1部分,求其最大乘积
	 * @param integerNum: 待拆分的自然数
	 * @param mSignNum:待插入的乘号数
	 * @return 最大乘积
	 */
	public static long handleMaximumMultiplicationWithMultipleSign(String integerNum, int mSignNum)
	{
		if(integerNum==null||mSignNum<0||mSignNum>=integerNum.length())
			throw new IllegalArgumentException("Wrong Arguments Input!");
	
		boolean result = isNaturalNumber(integerNum);
		
		if(!result)
			throw new IllegalArgumentException("Please input a natural number!");
		
		int numLength=integerNum.length();
		int[][] dpMultiTable=new int[numLength+1][mSignNum+1];//动态规划二维表
		
		for(int t=1;t<=numLength;t++)//初始化动态规划二维表:填入插入0个乘号的值
		{
			dpMultiTable[t][0]=Integer.parseInt(integerNum.substring(0,t));
		}
		
		for(int r=1;r<=mSignNum;r++)//填充动态规划二维表(乘号数目是一维:x)
		{
			for(int i=r+1; i<=numLength;i++)//构造动态规划二维表(当前扫描字符串是一维:y)
			{
				//状态遍历(从r-1个乘号的状态到r个乘号的状态),寻找当前f(i,r)的最优解并记录
				//j是插入第r个乘号的可能位置
				int current_max=0;
				for(int j=r;j<i;j++)
				{
					int currentvalue=dpMultiTable[j][r-1]*Integer.parseInt(integerNum.substring(j,i));
					if(current_value>current_max)
					{
						dpMultiTable[i][r]=current_value;
						current_max=current_value;
					}
				}
			}
		}
		
		return dpMultiTable[numLength][mSignNum];	
	}


	/**
	 * 判断输入是否是自然数
	 * @param integerNum
	 * @return
	 */
	public static boolean isNaturalNumber(String integerNum) {
		String reg = "^[1-9](\\d*)$";
		Pattern p = Pattern.compile(reg);
		Matcher m = p.matcher(integerNum);
		boolean result = m.find();
		return result;
	}


	/**
	 * @param args
	 */
	public static void main(String[] args) {

        System.out.println(handleMaximumMultiplicationWithMultipleSign("12345",2));
        System.out.println(handleMaximumMultiplicationWithMultipleSign("10",0));
	}

}

 

0
1
分享到:
评论

相关推荐

    算法-最大K乘积问题

    这样,在处理每个新元素时,我们可以比较并更新这两个堆,确保始终得到前k个最大乘积。 算法设计步骤如下: 1. 初始化两个大小为k的最小堆,一个用于正数,一个用于负数。 2. 遍历输入数组nums,对于每个元素: -...

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

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

    乘积最大子数组(动态规划)1

    首先,我们要明确动态规划的基本思路:从数组的第一个元素开始,逐步计算每个子数组的最大乘积,并保持一个全局最优解。对于数组中的每个元素,我们需要考虑两种情况:当前元素乘以前一个子数组的最大乘积是否更大,...

    动态规划k乘积问题.doc

    【动态规划k乘积问题】是一种经典的算法问题,主要涉及动态规划和贪心算法的运用。该问题的目标是给定一个n位十进制整数I和一个整数k,将其划分为k段,求得这k段整数的乘积最大化。下面将详细解析这个问题的解决策略...

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

    2. 动态规划过程:对于`j&gt;=2`的情况,我们可以遍历所有可能的分隔点`d`(1),计算`m[d][j-1]`(前d位分成j-1段的最大乘积)与`w[d+1][i]`(从第d+1位到第i位的值)的乘积,然后选取其中的最大值赋给`m[i][j]`。...

    最大子数组乘积

    在编程领域,"最大子数组乘积"是一个经典的问题,主要涉及到数组处理和动态规划算法。这个问题要求我们从一个整数数组中找到连续子数组,使得这个子数组的所有元素乘积最大。这个问题不仅出现在面试中,也是数据分析...

    javascript-leetcode面试题解动态规划问题之第152题乘积最大子数组-题解.zip

    动态规划是解决这些问题的一种重要算法,尤其在处理数组问题时,它能有效地找到最优解。第152题,即“乘积最大子数组”,是LeetCode中的一道经典动态规划题目,它要求我们找出数组中乘积最大的连续子数组。 动态...

    1821:【00NOIP提高组】乘积最大

    该问题可以使用递归和动态规划的方法来解决。 首先,需要了解 C++ 的基础知识,包括数组、函数、递归和动态规划等。 在该题目中,我们使用了一个二维数组 g 来存储中间结果,以避免重复计算。同时,我们使用递归...

    算法最大K乘积

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

    乘积最大的拆分.zip

    在动态规划的过程中,我们需要维护两个变量,一个是当前最大乘积,另一个是最小负数乘积(因为连续的负数相乘后可能成为正数,从而提高总乘积)。这样可以确保在处理负数时能获得最佳结果。 标签“算法”表明这个...

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

    最大 k 乘积是动态规划经典问题之一。该问题可以描述为:给定一个数组 a,有 n 个元素,每个元素都是一个正整数。我们需要找到数组 a 中的最大 k 乘积。这个问题可以使用动态规划来解决。我们可以使用一个二维数组 m...

    Leetcode最大乘积和19.10.3_leetcode_C++_

    描述中的“找出数组中连续相乘后能得出最大乘积的一组数字,算法十分精妙”揭示了我们需要解决的核心问题:在给定的整数数组中找到一个子数组,使得这些元素相乘得到的最大乘积。 这个问题属于数组和动态规划的范畴...

    NOIP复赛专题\动态规划(dp)Pascal

    综上所述,动态规划是信息学竞赛中的核心技能之一,对于Pascal程序员来说,熟练运用动态规划可以解决许多复杂的计算问题。通过深入理解并实践数塔、最长不下降序列、乘积最大问题等经典例子,可以有效提升编程思维和...

    连续子序列最大和与乘积问题的分析

    一个常见的解法是使用动态规划,同时跟踪最大和最小乘积,因为在负数之后,最小乘积可能成为新的最大乘积。 例如,如果有一个数组`[-2, 0, -1, 3, -4]`,最大乘积不是`3`,而是`-2 * -1 * 3 = 6`。这是因为负数与...

    php-leetcode题解之乘积最大子序列.zip

    动态规划是一种将大问题分解为小问题,逐步求解的方法。我们可以创建两个变量`$maxProduct`和`$minProduct`来分别记录到目前为止遇到的最大乘积和最小乘积。因为最小乘积在遇到负数时可能会变成最大乘积,所以这两个...

    蓝桥杯c++-蓝桥杯竞赛练习之算法提高题最大乘积.zip

    对于“最大乘积”问题,一种常见的解决方案是使用动态规划(Dynamic Programming, DP)。例如,可以维护两个变量,一个表示当前为止遇到的最大乘积,另一个表示最小乘积(因为负数乘以负数会变成正数),然后遍历数...

    python-leetcode面试题解之第152题乘积最大子数组-题解.zip

    3. 双指针:虽然动态规划是解决这个问题的常见方法,但也可以使用双指针来寻找最大乘积子数组。这种方法需要在遍历数组的过程中,比较相邻元素的乘积与当前最大值和最小值,不断更新这两个值。 4. 时间复杂度与空间...

    动态规划经典题打包下载1

    动态规划可以用来处理这个问题,通过维护两个动态规划数组,分别记录到当前位置为止的最大乘积和最小乘积(因为负数乘以最大乘积可能会变成最小,反之亦然)。通过这样的方式,我们可以有效地避免每次计算时都要重新...

    程序设计基础徐明星w12-20141208-第11章-动态规划-最短路径-最大乘积.ppt

    【程序设计基础】\n\n在程序设计领域,动态规划是一种强大的算法,广泛应用于解决最优化问题,如求解最短路径和最大乘积等。本讲义将深入探讨动态规划在解决最短路径问题上的应用,特别是针对具有单行道特征的图形...

Global site tag (gtag.js) - Google Analytics