一道经典的动态规划问题题解
有一个由数字1,2,...,9组成的数字串(长度不超过200),问如何将M(M<=20)个加号("+")插入到这个数字串中,使所形成的算术表达式的值最小。请编一个程序解决这个问题。
注意:
加号不能加在数字串的最前面或最末尾,也不应有两个或两个以上的加号相邻。
M保证小于数字串的长度。
例如:数字串79846,若需要加入两个加号,则最佳方案为79+8+46,算术表达式的值133。
[输入格式]
从键盘读入输入文件名。数字串在输入文件的第一行行首(数字串中间无空格且不折行),M的值在输入文件的第二行行首。
[输出格式]
在屏幕上输出所求得的最小和的精确值。
[输入输出举例]
EXAM4.SAM
82363983742
3
输 入 输 出
EXAM4.SAM 2170
易知,若用蛮力法进行求解,够呛了。明显,这是道经典的动态规划问题:
规划方程:
getResult[start,end]=min{getResult[start,index]+Num[index,end]} (start<index<=end-1)
边界值: getResult[0,end]= NUM[1,end] ;
其中:getResult[start,end]表示数字串第start到end位最小和
Num[index,end]表示数字串从第index到end位所组成的数
注意到上式中,index取值范围极广。然而我们对该题细细分析时,发现当最小和时,组成该最小和的任意两个加法因子的长度不大于1;
故每个加法因子长度只的可能为m/(n+1)或m/(n+1)+1(这里m表示数字串的长度,n表示加法号个数),当(n+1)|m时,每个数字串长度便确定了,可直接求出。有了此约束条件,该算法的复杂度便下降了。其java实现程序如下:
import javax.swing.*;
import java.math.*;
public class Adders {
private String numExp; //定义数字串
private int addNum; //定义加法号个数
private int lengthPerNum; //定义每个加法因子的最小长度
public Adders(){
//输入数字串和加法号个数,并求得LengthPerNum
numExp = JOptionPane.showInputDialog(null,"Please input the expression of numbers:");
addNum = Integer.parseInt(JOptionPane.showInputDialog(null,"the number of adding :"));
lengthPerNum = numExp.length() / (addNum + 1);
}
//将数字串strNum转为数字
private BigInteger num(String strNum){
if(strNum.equals("")) return new BigInteger("9999999999");
return new BigInteger(strNum);
}
//动态求得结果
public BigInteger getResultByDp(int index,int num){
if(num == 0)
return num(numExp.substring(0, index));
else{
BigInteger result1;
BigInteger result2;
if(index<=lengthPerNum+1 )
return new BigInteger("999999999");
result1 = getResultByDp(index - lengthPerNum,num - 1).add(num(numExp.substring(index - lengthPerNum, index))) ;
result2 = getResultByDp(index - lengthPerNum - 1,num - 1).add(num(numExp.substring(index - lengthPerNum - 1, index))) ;
if(result1.compareTo(result2)>= 0)
return result2;
else
return result1;
}
}
//直接求得结果
public BigInteger getResultByDiret(){
BigInteger result = new BigInteger("0") ;
for(int i=0;i <= addNum;i++)
result = result.add(num(numExp.substring(i*lengthPerNum,(i+1)*lengthPerNum)));
return result;
}
public static void main(String args[]){
Adders a = new Adders();
if(a.numExp.length() == (a.addNum+1)*a.lengthPerNum)
System.out.println("Result:"+a.getResultByDiret());
else
System.out.println("Result:"+a.getResultByDp(a.numExp.length(), a.addNum));
}
}
说明:1)这里仅仅实现了求最小和功能,并未严格遵循输入输出规则。
为了防止溢出,使用了高精度数BigInteger。
2)当然,由于长度为m/(n+1)和m/(n+1)+1的加法因子个数是确定的,也可以据此用枚举法实现,这里不再赘述。
3)水平有限,欢迎大牛提出宝贵意见。
分享到:
相关推荐
本题解聚焦于LeetCode中的第70题——"爬楼梯",这是一道典型的动态规划问题。动态规划是一种解决复杂问题的有效方法,它通过将大问题分解为小问题,然后存储并重用子问题的解决方案,从而避免了重复计算。 爬楼梯...
对于正在准备JavaScript和LeetCode面试的求职者来说,理解和掌握这类动态规划问题是至关重要的,因为它不仅展示了对算法的理解,还能体现解决问题的能力。通过解决类似的问题,开发者可以提高自己的编程技巧,增强在...
这是一道经典的算法问题,常见于求职面试,尤其是对于寻找前端开发职位的应聘者。下面将详细探讨这个问题的背景、解题思路以及如何使用动态规划来解决它。 ### 问题背景 LeetCode第416题(Split Array into ...
本压缩包文件“javascript-leetcode面试题解动态规划问题之第1143题最长公共子序列-题解.zip”包含了关于动态规划解决方案的详细解析,这是一道典型的算法面试题。 动态规划是一种解决复杂问题的有效方法,它通过将...
动态规划是一种通过将复杂问题分解为较小的子问题来解决的方法。它通常用于解决具有重叠子问题和最优子结构的问题。在这个问题中,我们需要找到一种方法,将给定的一系列有起始和结束时间的区间进行排序,使得尽可能...
这个名为“js-leetcode题解之种花问题-题解.zip”的压缩包文件,显然是针对LeetCode中的一道具体题目——“种花问题”提供了JavaScript的解决方案。下面,我们将详细探讨这道题目及其解题策略。 “种花问题”通常是...
题目来源于PKU ACM (Peking University ACM Programming Contest),是一道动态规划相关的编程题。 #### 2. 题目编号 题目编号为1179。 #### 3. 解题目标 本题的目标是通过动态规划算法求解最优解,并给出具体的...
这里的每一道题目都可能涉及到不同的算法和数据结构,例如排序、搜索、图论、动态规划等。通过这些题目的解题报告,学习者可以深入理解如何运用C/C++语言来解决实际问题,并掌握各种复杂问题的解题思路。 【标签】...
在JavaScript编程领域,LeetCode是一个非常受欢迎的在线平台,它提供了大量的编程题目...通过深入理解和实践这份题解,开发者可以更好地掌握在JavaScript中解决字符串问题的技巧,并扩展对动态规划和回溯法的应用理解。
涵盖利用递归方法规避租赁矛盾、采用蚁群碰撞模拟策略探究疾病传播规律以及借助动态规划探索宝藏收集最优路径等问题。帮助参赛者从实战出发深入理解和掌握递归方法、动态规划和模拟算法等多种解决问题的高效技术途径...
例如,快速排序在处理大规模数据时表现出高效率,而动态规划则常用于解决具有重叠子问题和最优子结构的问题。 其次,题目还可能涵盖高级算法,如字符串匹配(KMP、Boyer-Moore、Rabin-Karp)、网络流、线性规划、...
【北大ACM题解】- Trade on Verweggistan ...这是一道结合实际背景的动态规划问题,不仅考验选手对算法的理解,还要求对问题建模的能力。理解和解决这类问题有助于提升分析和解决问题的综合能力。
在LeetCode平台上,第53题被称为“Maximum Subarray”,这是一道经典的动态规划问题,旨在找到一个数组中的连续子数组,使得该子数组的和最大。在Python编程中,解决这个问题有多种方法,包括但不限于动态规划、分治...
然后,使用动态规划的思想,定义了两个类型的转移:f(i′, j) → f(i, j) 或者 f(i′, j) → f(i, j + 1) (i′ ≤ R(i′) + 1)。最后,根据 n2 = 2(n2)+(n1),答案为 2f(|S|, 2) + f(|S|, 1)。时间复杂度为 O(n log ...
这是一道经典的计算机科学问题,旨在考察应聘者的链表处理能力和动态规划的掌握程度。下面将详细讨论这个题目以及其解题策略。 LeetCode的第128题,名为"Longest Consecutive Sequence",要求找到给定无序整数数组...
标题中的“爬楼梯”问题是一道经典的算法题,源自LeetCode网站上的第70题,题目涉及动态规划和递归两种解决策略。本题的主要目的是考察程序员对算法的理解和运用能力,尤其在优化时间和空间复杂度方面。在求职面试中...
“跳跃游戏II”是一个经典的动态规划问题,它的背景是:给定一个非负整数数组,数组中的每个元素代表你在该位置可以跳跃的最大距离,你需要找出到达数组最后一个元素的最短跳跃次数。这道题目的挑战在于,每次跳跃...
4. **动态规划**:1015题"Euclid's Game"可能需要使用到动态规划解决递归问题,例如欧几里得算法求最大公约数。 5. **数组处理**:2481题"Unique Ascending Array"要求处理数组的排序和去重问题,可能需要用到排序...
**结论**:通过动态规划结合数论中的基本原理,可以有效地解决此类问题,而位压缩技术则是优化运行速度的一种有效手段。 --- #### FenceRails(fence8) **问题背景**:这是一道关于切割木板以满足建造围栏需求的...