动态规划

    动态规划主要用于求解包含重叠子问题的最优化问题的方法。其基本思想是,将原问题分解为相似的子问题,在求解的过程中通过子问题的解求出原问题的解。

 

应用动态规划有两个基本条件:

1.最优子结构

将问题分解为子问题,子问题最优解决定全局最优解。

2.子问题重叠性质

子问题重叠性质是指在用递归算法自顶向下对问题进行求解时,每次产生的子问题并不总是新问题,有些子问题会被重复计算多次。

动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只计算一次,然后将其计算结果保存在一个表格(数组)中,当再次需要计算已经计算过的子问题时,只是在表格中简单地查看一下结果,从而获得较高的效率。

 

通常动态规划算法有两种方式:自顶向下和自底向上。

1.自顶向下

是一种递归前进的设计策略。递归步骤首先查看数组中是否存在已被计算的结果。如果存在,直接返回此结果,如果不存在,那么递归就首先执行计算,然后将计算结果写入数组。这样可以使得后面的递归步骤能够对其进行访问。自顶向下编程也被称为:记忆(memorization)。

2.自底向上

将递归算法替换为使用存储容器和迭代的算法。它从最底层顺序填充容器(数组),迭代过程每个步骤都是用先前计算好的值来计算下一个值。

 

/**
 * dynamic programming
 * @author wll
 *
 */
public class DynamicProgramming {
 
 public static void main(String[] args) {
  int result=binomial(88,7);
  System.out.println(result);
  //----------------------------
  final int NUM = 40;
  int[]flist=new int[NUM+1];  
  int f=fibDynamic(NUM,flist);
  System.out.println(f);
  //-----------------------------
  int f2=fibDynamic2(NUM);
  System.out.println(f2);
 }
 
 /**bottom-up dynamic programming
  * compute C(n,k) with time efficiency O(n)
  *
  * @return return C(n,k)
  */
 private static int binomial(int n,int k){
  //create an n+1 by k+1 matrix
  int[][]C=new int[n+1][k+1];
  
  //rows range from 0 through n
  for(int i=0;i<=n;i++){
   int min=i>k?k:i;
   //only generate columns 0 through min
   for(int j=0;j<=min;j++){
    //C[i][j]=1 when j==0 or j==i
    if(j==0 || j==i)
     C[i][j]=1;
    else
     C[i][j]=C[i-1][j-1]+C[i-1][j];
   }
  }
  //return the entry C(n,k)
  return C[n][k];
 }
 /**
  * up-bottom dynamic programming
  * @param n
  * @param fibs
  * @return
  */
 private static int fibDynamic(int n,int[]fibs)
 {
  //initialize the value with -1
  int fibValue=-1;
  
  //first search the array
  if(fibs[n]>0)
   return fibs[n];
  
  //n==0 set fibValue 0;
  //n==1 set fibValue 1
  if(n<=1)
   fibValue=n;
  else
  fibValue=fibDynamic(n-1,fibs)+fibDynamic(n-2,fibs);
  //set the value fibValue to fibs[n]
  fibs[n]=fibValue;
  
  //return the entry fib(n)
  return fibValue;
  
 }
 /**
  * bottom-up dynamic programming
  * @param n
  * @return the result of fibonacci
  */
 private static int fibDynamic2(int n)
 {
  //create an n+1 array
  int[]fibs=new int[n+1];
  //initialize
  fibs[1]=1;
  fibs[2]=1;
  
  //range from 3 through n
  for(int i=3;i<=n;i++)
  {
   //fill the array,generate fibs(i)
   fibs[i]=fibs[i-1]+fibs[i-2];
  }
  
  return fibs[n];
 }
 /**
  * recursive method with low efficiency.
  * compute the value of C(n,k)
  *
  * @param n
  * @param k
  * @return the result of C(n,k)
  */
 private static int binomial2(int n,int k){
  if(k>n)
   throw new
   IllegalArgumentException("wrong arguments!!!");
  //C(n,k)==1 when k==0 or n==k
  if(k==0 || n==k)
   return 1;
  else
   return binomial2(n-1,k-1)+binomial2(n-1,k);
 }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值