动态规划算法学习十例之二



例一:计算二项式系数:

   在排列组合里面,我们有下面的式子(很容易用组合的定义来证明):



   这个式子将C(n , k)的计算问题表述为了(问题描述)C(n-1 , k -1)和C(n -1, k)两个较小的重叠子问题。
/* 
 * 用动态规划算法计算C(n,k) 
 * 输入:一对非负整数n>=k>=0 
 * 输出:C(n,k)的值 
 */  
import java.util.*;  
  
public class Binomial {  
    int C[][];  
    int Computing(int n,int k){  
        C = new int[n+1][n+1];  
        for(int i=0;i<=n;i++){  
            for(int j=0;j<=Math.min(i, k);j++){  
                if(j==0||j==i){  
                    C[i][j] = 1;  
                }  
                else{  
                    C[i][j] = C[i-1][j-1]+C[i-1][j];  
                }  
            }  
        }  
        return C[n][k];  
    }  
    public static void main(String[] args) {  
        Scanner in = new Scanner(System.in);  
        System.out.println("请输入n:");  
        int n = in.nextInt();  
        System.out.println("请输入k(0<=k<=n):");  
        int k = in.nextInt();  
        Binomial b=new Binomial();
        System.out.println("C["+n+","+k+"] = "+b.Computing(n, k));    

       for(int i = 0;i <= 8;i++)   
         System.out.println("C" + "[" + 8 + "," + i + "]" + " ———— " +b.Computing(8,i));
    
    }  
}  




运行:
C:\java>java   Binomial
请输入n:
5
请输入k(0<=k<=n):
5
C[5,5] = 1
C[8,0] ———— 1
C[8,1] ———— 8
C[8,2] ———— 28
C[8,3] ———— 56
C[8,4] ———— 70
C[8,5] ———— 56
C[8,6] ———— 28
C[8,7] ———— 8
C[8,8] ———— 1

例二:斐波那契数列(动规实现)
  无穷数列1,1,2,3,5,8,13,21,34,55,…,被称为Fibonacci数列。它可以递归地定义为:
动态规划算法学习十例之二

2 程序实现

缓存是为了减少重复计算。

import java.util.HashMap;

import java.util.Map;

 

public class FibonacciUtil {

    static Map<Integer, Integer> cache = new HashMap<Integer, Integer>();

 

    public static int fib(int n) {

        if (n == 0 || n == 1)

            return 1;

        if (null != cache.get(n))

            return cache.get(n);

                

        int ret = fib(n - 1) + fib(n - 2);

        cache.put(n, ret);

        return ret;

    }

        

    public static void listFib(int n){

        for(int i=1;i<n;i++){

            System.out.print(fib(i)+",");

        }

    }

        

    public static void main(String[] args) {

        listFib(10);

    }

}


若求问题的唯一解(最优解),先分解成为子问题,而子问题的解也是唯一的(最优的)。子问题有重叠,为了减少重复计算,缓存重叠部分计算结果;
这两点也正是动规算法的精髓。实际上,这个例子是动规算法最简单的一个实例。

下载源代码。

你可能感兴趣的:(java,数据结构,编程,算法)