动态规划的两种形式
自顶而下的备忘录形式
自下而上的动态规划
现在均使用Fib序列做个例子,具体代码和注释如下图:
/**
* 动态规划分为两种:
* 一种的是自下而上的动态规划
* 一种是自上而下的备忘录方法
*
* @author jhc
*
*/
public class FibTest {
/**
* 自下而上的备忘录方法
* mem作为备忘录一开始便创建一个空的一维数组用来存储各节点之间的值
* 这个还是用到了递归的方法
*
*/
public static int fibUpToBottom(int n,int[] mem){
if(mem[n] != -1){
return mem[n];
}
if(n<=2){
return 1;
}else{
mem[n] = fibUpToBottom(n-1,mem)+fibUpToBottom(n-2,mem);
}
return mem[n];
}
/**
* 上面的方法还是采用了递归的方法,我们可以自底而上的方法不用采用递归的方法
* @param n
* @return
*/
public static int fibBottomToUp(int n){
int[] mem = new int[n+1];
mem[0] = 0;
mem[1] = 1;
mem[2] = 1;
for(int i=3;i<=n;i++){
mem[i] = mem[i-1] + mem[i-2];
}
// System.out.println("---");
// for(int i=0;i<=n;i++){
// System.out.print(mem[i]);
// }
// System.out.println("");
// System.out.println("----");
return mem[n];
}
/**
* 也可以不用一个数组来表示,因为实际上只用到了三个数字
*/
public static int fibBottomToUpSimple(int n){
if(n <= 0) return n;
int memI2 = 0;
int memI1 = 1;
int memI = 1;
for(int i=2;i<=n;i++){
// System.out.print(memI+" ");
/**
* 注意先后顺序的问题很重要容易搞错
*
*/
memI = memI2 + memI1;
memI2 = memI1;
memI1 = memI;
}
return memI;
}
public static void main(String[] args){
int[] temp = new int[6];
for(int i=0;i<=5;i++){
temp[i] = -1;
}
System.out.println(fibUpToBottom(5,temp));
System.out.println(fibBottomToUpSimple(5));
System.out.println(fibBottomToUp(5));
}
}
钢条切割
package com.jhc.动态规划解决.钢条切割;
/**
* 自下向上的动态规划算法
* 用一个Solution数组来存储,而最优子结构为当前值要和前面所有的可能进行比较
* 我的做法是每次更新Solution
* 利用Solution不断去找到最适合我的值 找全所有的可能
*
* @author jhc
*
*/
public class Solution {
private static int[] value = {0,1,5,8,9,10,17,17,20,24,30};
public static int mostValue(int n){
int[] solution = new int[n+1];
solution[1] = value[1];
for(int i=2;i<=n;i++){
solution[i] = value[i];
for(int j=1;j<i;j++){
solution[i] = Math.max(solution[i-j]+value[j],solution[i]);
}
}
return solution[n];
}
public static void main(String[] args){
System.out.println(mostValue(4));
}
}