<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Change Dir

    先知cd——熱愛生活是一切藝術(shù)的開始

    統(tǒng)計

    留言簿(18)

    積分與排名

    “牛”們的博客

    各個公司技術(shù)

    我的鏈接

    淘寶技術(shù)

    閱讀排行榜

    評論排行榜

    深入理解動態(tài)規(guī)劃的一系列問題(12)

    今天介紹三個經(jīng)典問題,為什么直接來三個?大概是因為這三個問題我覺得太經(jīng)典了,以至于在任何人學習任何語言時都可能要實現(xiàn)這些題目的編程訓練,所以這里就放到一起,打包講下求解這些問題的動態(tài)規(guī)劃思路(雖然有些問題不是那么直觀的動態(tài)規(guī)劃解)。

    第一個問題是編輯距離(Edit Distance Problem)EDP問題,這個問題在維基上有全面的解釋,并附有準確的代碼實現(xiàn)(也叫l(wèi)evenshtein距離),我這里就簡單講下遞歸的DP解法。編輯距離需要一些前置條件,首先是距離的定義:對于兩個字符串x和y,其中x包含m個字符,y包含n個字符,目標是由x串經(jīng)過一系列允許的操作后變到y(tǒng)串,這些操作包括:1)刪除操作D,刪掉任意一個字符,成本為c(D);2)插入操作I,插入任意一個字符,成本為c(I);3)替換操作R,替換掉字符串中的一個字符,成本為c(R)。當然變?yōu)閥串后要求變化成本最優(yōu)。這就是一個典型的DP問題了。定義狀態(tài)(i,j)為x串的前i個字符(即i串前綴),y串的j串前綴,于是DPFE為:image 。換種表達就是image ,轉(zhuǎn)移函數(shù)t表示如下:image 。目標就是計算f(x,y)。

    舉例來說:x="CAN”,y=”ANN”,三種操作的成本均為1,求x和y的編輯距離。(答案為2,具體求解見下面代碼)

    源碼求解:

       1: /*
       2:  * Copyright (C) 2013 changedi
       3:  *
       4:  * Licensed under the Apache License, Version 2.0 (the "License");
       5:  * you may not use this file except in compliance with the License.
       6:  * You may obtain a copy of the License at
       7:  *
       8:  * http://www.apache.org/licenses/LICENSE-2.0
       9:  *
      10:  * Unless required by applicable law or agreed to in writing, software
      11:  * distributed under the License is distributed on an "AS IS" BASIS,
      12:  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13:  * See the License for the specific language governing permissions and
      14:  * limitations under the License.
      15:  */
      16: package com.jybat.dp;
      17:  
      18: //EditDistanceProblem;
      19: public class EDP {
      20:  
      21:     private static String s1 = "CAN";
      22:     private static String s2 = "ANN";
      23:     private static final int insertionCost = 1;
      24:     private static final int deletionCost = 1;
      25:     private static final int replacementCost = 1;
      26:     // it is useful to have the string lengths as symbolic constants
      27:     private static int s1Length = s1.length();
      28:     private static int s2Length = s2.length();
      29:  
      30:     // The decision space is constant in this example.
      31:     // It does not depend on the current state.
      32:     // We chose to code the 3 allowed operations
      33:     // as follows:
      34:     // 1 stands for delete
      35:     // 2 stands for insert
      36:     // 12 stands for replace
      37:     private static int[] decisionSet = { 1, 2, 12 };
      38:  
      39:     // costOfOperation()
      40:     // returns 0 if the specified characters in the 2 strings
      41:     // match and the decision is to perform
      42:     // "replacement" operation for matching chars
      43:     // (whose cost is usually defined as 0)
      44:     // returns 1 otherwise (if delete, insert, or a real replacement operation
      45:     // happens)
      46:     private static int costOfOperation(int i, int j, int dec) {
      47:         if (dec == 12) { // dec==12 means decision is to replace
      48:             if (s1.charAt(i - 1) // note: subtract 1 because array
      49:             // starts at index 0
      50:             == s2.charAt(j - 1)) { // matching chars, cost is 0
      51:                 return 0;
      52:             } else { // real replacement
      53:                 return replacementCost; // cost of real replacement
      54:             }
      55:         }
      56:         if (dec == 1) { // dec==1 means decision is to delete
      57:             return deletionCost;
      58:         }
      59:         // otherwise it must be that dec==2, decision to insert
      60:         return insertionCost;
      61:     }
      62:  
      63:     private static int s1Adjustment(int dec) {
      64:         if (dec == 2) { // insert
      65:             return 0;
      66:         }
      67:         return 1;
      68:     }
      69:  
      70:     private static int s2Adjustment(int dec) {
      71:         if (dec == 1) { // delete
      72:             return 0;
      73:         }
      74:         return 1;
      75:     }
      76:  
      77:     public static int d(int i, int j) {
      78:         if (i == 0)
      79:             return j;
      80:         if (j == 0)
      81:             return i;
      82:         int min = Integer.MAX_VALUE;
      83:         for (int dec : decisionSet) {
      84:             int t = costOfOperation(i, j, dec)
      85:                     + d(i - s1Adjustment(dec), j - s2Adjustment(dec));
      86:             if (t < min)
      87:                 min = t;
      88:         }
      89:         return min;
      90:     }
      91:  
      92:     /**
      93:      * @param args
      94:      */
      95:     public static void main(String[] args) {
      96:         System.out.println(d(s1Length, s2Length));
      97:  
      98:     }
      99:  
     100: }

    第二個問題是大家非常熟悉的斐波那契數(shù)列問題Fibonacci Recurrence Relation (FIB):

    斐波那契數(shù)列就是一個經(jīng)典的f(n)=f(n-1)+f(n-2)的遞歸問題。這里不講,只是列出這個問題。

    第三個問題是漢諾塔問題Tower of Hanoi Problem (HANOI):

    漢諾塔的問題描述就省去了,主要是定義狀態(tài),我們定義在移動了i個碟子后的最優(yōu)步數(shù)為f(i),則f(i)=2f(i-1)+1,即通用的漢諾塔策略:將碟子先移動到中間柱,移動i-1個后,將第i個碟子移動到目標柱,然后再重復將i-1個柱子以同樣的方法放回目標柱,于是這個dp方程就可以理解了。但是這樣子的方程看上去總不像動態(tài)規(guī)劃那明細的階段和狀態(tài)的對應,于是我們修正一下方程如下:f(m,i,j,k)=opt {f(m-1,i,k,j)+f(1,i,j,k)+f(m-1,k,j,i)}。狀態(tài)(m,i,j,k)表示把m個碟子從i移動到j的最優(yōu)步數(shù),k代表中間那個柱。

    DP源碼如下:

     

       1: /*
       2:  * Copyright (C) 2013 changedi
       3:  *
       4:  * Licensed under the Apache License, Version 2.0 (the "License");
       5:  * you may not use this file except in compliance with the License.
       6:  * You may obtain a copy of the License at
       7:  *
       8:  * http://www.apache.org/licenses/LICENSE-2.0
       9:  *
      10:  * Unless required by applicable law or agreed to in writing, software
      11:  * distributed under the License is distributed on an "AS IS" BASIS,
      12:  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13:  * See the License for the specific language governing permissions and
      14:  * limitations under the License.
      15:  */
      16: package com.jybat.dp;
      17:  
      18: //tower of hanoi problem
      19: //Compute the number of moves when the recursive
      20: //strategy is used. 
      21: public class HANOI {
      22:  
      23:     // m: number of disks to move
      24:     // i: index of source tower
      25:     // j: index of destination tower
      26:     // k: index of temporary tower
      27:     public static int f(int m, int i, int j, int k) {
      28:         if (m == 1)
      29:             return 1;
      30:         return f(m - 1, i, k, j) + f(1, i, j, k) + f(m - 1, k, j, i);
      31:     }
      32:  
      33:     /**
      34:      * @param args
      35:      */
      36:     public static void main(String[] args) {
      37:         System.out.println(f(3,1,2,3));
      38:     }
      39:  
      40: }

    總結(jié)下,其實這三個問題,除了編輯距離外,fib和hanoi都更像是遞歸教學而不是DP,但是其實從問題的結(jié)構(gòu)上講,hanoi這樣的是典型的動態(tài)規(guī)劃求解,只不過過多的教科書和經(jīng)驗把它們放到了遞歸里,同時又忽略了遞歸和DP的聯(lián)系。所以我這里把它們放到一起,用來說明動態(tài)規(guī)劃問題也包含經(jīng)典的遞歸問題的。

    posted on 2014-05-27 10:38 changedi 閱讀(1870) 評論(0)  編輯  收藏 所屬分類: 算法

    主站蜘蛛池模板: 黄色免费在线网站| 一本一道dvd在线观看免费视频| 亚洲伊人久久大香线蕉AV| 亚洲heyzo专区无码综合| 免费在线人人电影网| 一个人看的www免费视频在线观看| 一级毛片免费观看| 国产精品久久久久久久久久免费| 四虎免费影院4hu永久免费| 自拍偷自拍亚洲精品被多人伦好爽| 亚洲天堂久久精品| 亚洲人成未满十八禁网站| 一区二区三区在线观看免费| 久久午夜夜伦鲁鲁片免费无码| 免费精品人在线二线三线区别 | 中文字幕免费播放| 97公开免费视频| 国产免费无遮挡精品视频| 亚洲色偷偷偷鲁综合| 亚洲一区二区三区成人网站 | 国内大片在线免费看| 亚洲情侣偷拍精品| 亚洲第一页在线观看| 国产亚洲女在线线精品| 久9热免费精品视频在线观看| 免费黄色app网站| 国产亚洲综合色就色| 亚洲三级在线观看| a级毛片视频免费观看| 成年在线观看免费人视频草莓| 狠狠亚洲狠狠欧洲2019| 亚洲成aⅴ人在线观看| 九九九国产精品成人免费视频| 天天影视色香欲综合免费| www.亚洲精品.com| 亚洲国产精品日韩在线| h视频在线免费观看| 扒开双腿猛进入爽爽免费视频| 亚洲精品美女久久久久99| 亚洲国产成人久久综合| 67pao强力打造高清免费|