每日小记-动态规划:怎么使用迭代公式构造循环次序:以最优除法为例
记录了啥
动态规划中
在拿到迭代公式之后(也就是知道了如何利用已知部分的信息求未知部分的信息之后)
怎么写循环(怎么循环,好在里面写迭代公式)
题目
最优除法https://leetcode-cn.com/problems/optimal-division/
简单说:一个数组全是正整数,从第一个到最后一个挨个除÷,也就是a/b/c/d/e....、y/z
求:在里面添加括号来改变运算次序,求出最大结果
这道题有最脑残的解法(妈的答案是固定,把第二个到最后一个括起来就行,我说我怎么效率那么低,3层循环的动态规划效率能高就tm见鬼了)
但是用来锻炼一下动态规划还是可以的
简单说,
要构造一个三维(lenlen4)的存储空间来存放辅助数组
其中ij位置记录从i到j的数能形成的最大值和最小值
这样,根据(n,m)和(m+1,p)的信息就能知道(n,p)的信息
//最初我考虑的遍历方式就是三层,外层i,中层j,内层枚举k,其中:i
总结
动态规划的过程就是通过辅助空间记录之前求解过的过程,避免二次计算,
那么必须注意,如何安排循环方式使得在做某一次计算的时候,所需要的中间结果都是已经计算好的
本题我最初的考虑方式中,每一步求解时,都只知道了左段,不知道右段信息
因为我最外侧控制大的执行方向的变量是起始位置
而答案使用的是求解段的长度,这样长度从2开始增加,求解n长的时候,拆分的任何i,n-i两个段的信息都是求过的,已知的
直接贴代码吧
点击查看代码
public static String optimalDivision(int[] nums) {
int len=nums.length;
//后期为了字符串拼接方便啥的,可以考虑使用Stingbuffer
String[][][] maxMinString=new String[2][len][len];//最大值最小值对应的字符串
double[][][] maxMin=new double[2][len][len];//记录ij区间的公式的最大值和最小值
for (int i = 0; i < len; i++) {
for (int j = 0; j < len; j++) {
if(i==j){
maxMin[0][i][j]=nums[i];
maxMin[1][i][j]=nums[i];
maxMinString[0][i][j]=String.valueOf(nums[i]);
maxMinString[1][i][j]=String.valueOf(nums[i]);
}else{
maxMin[0][i][j]=0;
maxMin[1][i][j]=10000;
}
}
}
//最初我考虑的遍历方式就是三层,外层i,中层j,内层枚举k,其中:imaxMin[1][i][k]/maxMin[0][k+1][i+c]){
maxMin[1][i][i+c]=maxMin[1][i][k]/maxMin[0][k+1][i+c];
//更新字符串记录,和括号,除号
//首先,两端的最值的字符串长成啥样都记录下来了,那么整体的最一下拼接就行了,但是要注意,右侧长度大于1时要套括号
if((i+c)!=(k+1)){
maxMinString[1][i][i+c]=maxMinString[1][i][k]+"/("+maxMinString[0][k+1][i+c]+")";
}
else{
maxMinString[1][i][i+c]=maxMinString[1][i][k]+"/"+maxMinString[0][k+1][i+c];
}
}
//更新最大值,左端最大值/右端最小值
if(maxMin[0][i][i+c]