页面加载中...

动态规划算法

| 默认分类 | 0 条评论 | 858浏览

动态规划

动态规划算法是通过拆分问题,定义问题状态和状态之间的关系,使得问题能够以递推(或者说分治)的方式去解决。

简而言之,就是将一个大问题拆分成若干的子问题,即分而治之,通过解决逐个逐个小问题进而得到整个问题解的过程。允许这些子问题不独立。此外,也应该需要过自身子问题的解作出选择,该方法对每一个子问题只解一次,并将结果保存起来,避免每次碰到时都要重复计算。

因此,动态规划法所针对的问题有一个显著的特征,即它所对应的子问题树中的子问题呈现大量的重复。动态规划法的关键就在于,对于重复出现的子问题,只在第一次遇到时加以求解,并把答案保存起来,让以后再遇到时直接引用,不必重新求解。

 

斐波拉契数列

Fibonacci数列算是大学算法的通俗例子了。其概念整合成表达式如下:

f(n) = f(n-1)+f(n-2);
其中,f(0)=0,f(1)=1;

递归就是这样一种思路,首先,需要确定递归函数的临界条件是什么,如上n=0或n=1的条件。

通过代码表示如下:(Java,以下皆是):

    public int fib(int n){
        if (n==0){
            return 0;
        }
        if (n==1){
            return 1;
        }
        return simpleFibonacci(n-1)+simpleFibonacci(n-2);
    }

这样就表示出了Fibonacci函数。

但是,有个问题,重复的计算过多。

比如:计算fib(6)的结果,首先需要计算fib(5)和fib(4)的结果,计算fib(5)及又要计算fib(4)和fib(3)的结果,假设之前已经计算出了fib(4)的结果,那么计算fib(5)时又得计算fib(4)一次,以此类推,如下。

可见,重复得计算会很多。一种解决方案是做个备份,也就是说在计算出某个子问题的结果后,需要将其保存,进而避免重复的计算。所以,上面的代码可以优化成这样:

    /**     * 用一个map作为备份来保存每次计算的结果     */
    Map backup = new HashMap<>();
    public int backFibonacci(int n){
        //如果备份有该数据,则直接获取该值,无需计算
        if (backup.containsKey(n)){
            return backup.get(n);
        }
        if (n==0){
            backup.put(0,0);
            return 0;
        }
        if (n==1){
            backup.put(1,1);
            return 1;
        }
        int ret = backFibonacci(n-1)+backFibonacci(n-2);
        //将计算结果保存
        backup.put(n,ret);
        return ret;
    }

求钢条分割的例子

from:https://blog.csdn.net/u013309870/article/details/75193592

同样的,考虑到,一段n的钢条,假设其最优解的为f(n),那么必定满足:

f(n) = max(Pn,Pi+Pn-i)

这样,我们只需考虑将整个n先分成两段,一段i,一段n-i。(极限值就是i=n)。假设Pi的价格已经是最优解,这样,我们只需要Pn-i的最优解了,最后再通过比较,得出最终的最优解。

所以, 代码如下:

/**
     * 钢条切割的map,
     * key : 长度
     * value :为长度对应的钱
     */
    static Map gtqgMap = new HashMap<>();
    /**
     * 计算出n=i的最优解保存在此处
     */
    static Map gtqgMapBack = new HashMap<>();
    /**
     * 初始临界条件
     */
    static {
        gtqgMap.put(1,2);
        gtqgMap.put(2,5);
        gtqgMap.put(3,8);
        gtqgMap.put(4,9);
        gtqgMap.put(5,10);
        gtqgMap.put(6,17);
        gtqgMap.put(7,17);
        gtqgMap.put(8,20);
        gtqgMap.put(9,24);
        gtqgMap.put(10,30);
    }
       public int gangTiaoQieGeBack(int n){
        if (gtqgMapBack.containsKey(n)){
            return gtqgMapBack.get(n);
        }
        int p = 0;
        if (gtqgMap.containsKey(n)){
            p = gtqgMap.get(n);
        }
        for (int i=1;i

发表评论

最新评论

    来第一个评论吧!