前言
我是想通过一些例题分析来带领我和大家入动态规划的门,若是我哪里分析或思考的有误区,或者错误,请大家能够对我进行评论或私信指正
1.使用最小花费爬楼梯(Min Cost Climbing Stairs) Java动态规划入门分析一
2.打家劫舍(House Robber)Java动态规划入门分析二
3.剪绳子(CutRope) Java动态规划入门分析三
题干
给定一根长度为n的绳子,请把绳子剪成m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],…,k[m]。请问k[0]* k[1] * … *k[m]可能的最大乘积是多少?
示例1:
输入:8
输出:18
解释:当绳子的长度是8时,可以把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
动态规划入门分析
首先我们先做分析,当绳子长度分别为1,2,3的时候,1无法分割,2[1*1],3[1*2]只能分割为带1的乘积的,此时的分割没有意义(一是因为分割后的值,比本身都小,二是因为带有1,1没有意义),所以我们在以后的分割中不考虑有1的情况(比如例子中8可分割为1*7,这个值不做考虑),分割中有1的情况,没有意义,又因为从4开始可以分割出不带1的分割(2*2),所以我们的基础值应该为2,3,也就是说其他所有的数都可以用2,3组成,然后我们又应该分析状态转移方程:f(0) = 2,f(1) = 3,也就是说n = 4的时候,f(n-2) = f(2)等于4的最大值2*2 = f(0) * f(0),当n = 5的时候f(3) =Math.max(2*3 = f(0)f(1)) ,我们观察发现2*2 ,2*3 的规律为i n - i,所以状态转移方程f(n-2) = Math.max(f(i-2)*f(n-i-2)) {i为正整数,i > 1 && i < n - 1}
代码一
public static int cutRope(int length) {
if (length < 2) {
return 0;
}
if (length == 2) {
return 1;
}
if (length == 3) {
return 2;
}
int max = 0;
int res[] = new int[length];
res[0] = 2;
res[1] = 3;
for (int i = 4; i <= length; i++) {
max = 0;
for (int j = 2; j <= i / 2; j++) {
int r = res[j - 2] * res[i - j - 2];
if (max < r) {
max = r;
res[i - 2] = max;
}
}
}
max = res[length-2] ;
return max;
}
分析二
上面的分析得到了f(n-2) = Math.max(f(i-2)*f(n-i-2)) {i为正整数,i > 1 && i < n - 1},我们发现这个方程式有个共同点,他们都减去了2,此时我们是否可以这样?f(n) = Math.max(f(i)*f(n-i)) {i为正整数,i > 0 && i < n },这样的话,f(2) = 2, f(3) = 3,f(0),f(1)任意取值(也就是占个位置)
代码二
public static int cutRope(int length) {
if(length < 2 ) {
return 0;
}
if(length == 2) {
return 1;
}
if(length == 3) {
return 2;
}
int[] res = new int[length+1];
//任意赋值res[0],res[1]
res[0] = 0;
res[1] = 1;
res[2] = 2;
res[3] = 3;
int max = 0;
for(int i = 4 ; i <= length ; i ++) {
max = 0;
for(int j = 1 ; j <= i/2 ; j++) {
int r = res[j] * res[i-j];
if(max < r) {
max = r;
res[i] =max;
}
}
}
max = res[length];
return max;
}
若是哪里有理解错误的或写错的地方,望各位读者评论或者私信指正,不胜感激。