zoukankan      html  css  js  c++  java
  • 动态规划-练习

    动态规划范式

    var catch = [[],[]];

    function someObscureFunction(a,b){

      if(...) return ...;//先处理初始部分

      var ret = catch[a][b];

      if(ret) return ret

      return catch[a][b] = 求解

    }

    练习1 通配符

      *  长度大于等于0的字符串

      ?   任一字符串

    例如:

      he?p 匹配 help,heap,无法匹配helpp.

      *p* 匹配papa

    代码如下,这个算法的复杂度为O(n*n*n),n<=100 可以接受。

    <script>
    function matchMemozied(W1,S1){
        var cache = [];
        var W = W1.split(''),S = S1.split('');
        function match(w,s){
            var w1 = w,s1=s,ret;
            if(cache[w1]){
                if(cache[w1][s1]){
                    return cache[w1][s1];
                }
            }else{
                cache[w1] = [];
            }
            while(s<S.length && w< W.length && (W[w] == '?' || W[w] == S[s]))
            {
                ++w;
                ++s;
            }
            if(w == W.length )
            return cache[w1][s1] = s==S.length;
            if(W[w] == '*')
             {  for(var i=0;i+s<=S.length;i++){
                    if(match(w1+1,s+i)){
                        return cache[w1][s1] = 1;
                    }
                }
             }
             return cache[w1][s1] = 0;
        }
        if(match(0,0)){
            console.log(S1);
        }
    }
    matchMemozied('he?p','heap');
    matchMemozied('he?p','heapp');
    matchMemozied('*p*','papa');
    </script>

    代码二,O(n*n)

    <script>
    
    function matchMemozied(W1,S1){
        var cache = [];
        var W = W1.split(''),S = S1.split('');
        function match(w,s){
            var w1 = w,s1=s,ret;
            if(cache[w1]){
                if(cache[w1][s1]){
                    return cache[w1][s1];
                }
            }else{
                cache[w1] = [];
            }
            if(s<S.length && w< W.length && (W[w] == '?' || W[w] == S[s]))
            {
                return cache[w1][s1] = match(w+1,s+1);
            }
            if(w == W.length )
            return cache[w1][s1] = s==S.length;
            if(W[w] == '*')
             {
                if(match(w+1,s) || (s<S.length && match(w,s+1)))
                {
                    return cache[w1][s1] = 1;
                }
             }
             return cache[w1][s1] = 0;
        }
        if(match(0,0)){
            console.log(S1);
            console.log(cache);
        }
    }
    matchMemozied('he?p','heap');
    matchMemozied('he?p','heapp');
    matchMemozied('*p*','papa');
    </script>

     典型优化问题

      优化问题就是在多个答案中选择出最佳答案(最优解),动态规划法起初是从快速解决优化问题

      利用动态规划法解题也是从穷举搜索法开始的

    练习:三角形的最大路径问题

      6

      1  2

      3  7  4

      9  4  1  7

      2  7  5  9  4

    从6开始往下走,只能向下和右下走(此时不计算向右走的一步的所在的数字),最终到达底部,找出数值之和最大的路径。

    首先用穷举搜索法

    <script>
    var data = [[6],
                [4,5],
                [7,1,6],
                [3,5,5,2],
                [9,1,3,6,2]];
     function path1(y,x,sum){
        if(y == data.length - 1){
            return sum + data[y][x];
        }
        return  Math.max(path1(y+1,x,sum+data[y][x]),path1(y+1,x+1,sum+data[y][x]));
     }
    var max = path1(0,0,0); 
    console.log(max);
    </script>

     这个事枚举所有的,文章还提到另一种思路,找最优子结构

    <script>
    var j=0;
    function path2(y,x){
        j++;
        if(y === data.length -1){
            return data[y][x];
        }
        return Math.max(path2(y+1,x),path2(y+1,x+1)) + data[y][x];
    }
    console.time('path2');
    var max2 = path2(0,0,0); 
    console.timeEnd('path2');
    console.log('max2:' + max);
    console.log('j:' + j);
    </script>

    这两个方法都跑了2的n次方,现在加入动态规划范式,第一种解法加范式的话需要三维数组,而且实际上没有节省执行次数,所以就没试,下一题就涉及到修改输入值来方便动态规划。

    <script>
    var k=0,cache =[];
    for(var m = 0;m< data.length;m++){
        cache[m] = [];
    }
    function path3(y,x){
        k++;
        if(y === data.length -1){
            return data[y][x];
        }
        if(cache[y][x]){
            return cache[y][x];
        }else{
            return cache[y][x] = Math.max(path3(y+1,x),path3(y+1,x+1)) + data[y][x];
        }
        
    }
    console.time('path3');
    var max3 = path3(0,0,0); 
    console.timeEnd('path3');
    console.log('max3:' + max);
    console.log('k:' + jk);
    </script>

    从结果上看,执行次数明显减少,结果也是相同的,但是执行时间略有增加。。。下一题,呜呜

     最长递增子序列问题

      比如 1,2,4 是 1,5,2,4,7 的递增子序列

      先上枚举搜索算法

    <script>
    function list(A){
        var ret = 0;
        for(var i = 0;i<A.length;i++){
            var B = [];
            for(var j = i+1 ; j<A.length;j++){
                if(A[i]<A[j]){
                    B.push(A[j]);
                }
            }
            ret = Math.max(ret,1 + list(B));
        }
        return ret;
    }
    var c = 100,data =[];
    while(--c>0){
        data.push(Math.floor(Math.random()*20))
    }
    console.log(data);
    console.time('list');
    var result = list(data);
    console.timeEnd('list');
    console.log(result);
    </script>

    现在的输入是数组,不适合缓存定位,现改为数组的下标作为参数

    <script>
    function list1(start){
        var ret = 1;
        for(var i = start+1;i<data.length;i++){
            if(data[start]<data[i]){
                ret = Math.max(ret,1 + list1(i));
            }
            
        }
        return ret;
    }
    console.time('list1');
    var result = list1(0);
    console.timeEnd('list1');
    console.log(result);
    </script>

    现在加入动态规划,就是缓存啦

    <script>
    function list2(start){
        if(cache[start +1 ]){
            return cache[start + 1 ];
        }
        cache[start + 1 ] = 1;
        for(var i = start+1;i<data.length;i++){
            if(start == -1 || data[start]<data[i]){
                cache[start + 1 ] = Math.max(cache[start + 1 ],1 + list2(i));
            }
            
        }
        return cache[start + 1 ];
    }
    var cache = [],max=0;
    console.time('list2');
     
    for(var k = 0;k<data.length;k++){
        max = Math.max(max,list2(k));
    }
    console.timeEnd('list2');
    console.log(max);
    </script>

    总得时间复杂度还是n*n 的,还有更少的,n*logn 

  • 相关阅读:
    This iPhone 6s is running iOS 11.3.1 (15E302), which may not be supported by this version of Xcode.
    vmware 里MAC 鼠标能移动 无法单击
    php获取微信的openid
    PHP 调试打印输出变量
    E0264 Unable to execute '"/usr/bin/codesign" ...'
    PHP 返回JSON
    小米手机安装证书
    CSS3:radial-gradient,径向渐变的使用方法
    CSS3:linear-gradient,线性渐变的使用方法
    CSS3:RGBA的使用方法
  • 原文地址:https://www.cnblogs.com/poorpeople/p/7238233.html
Copyright © 2011-2022 走看看