動態規劃

1.動態規劃是什麼

動態規劃:經過分解問題,將複雜的問題分解爲最基本的小問題,找到局部的最優解,而後找到最終問題的最優解的過程。java

動態規劃關鍵:程序員

  • 狀態轉移
    • 字問題之間的轉移操做
  • 狀態轉移方程
    • 描述狀態轉移的表達式

2.動態規劃案例

案例選自 極客時間 程序員的數學基礎課數組

2.1.查詢推薦
  • 搜索引擎在搜索單詞的時候會有單詞的下拉提示和**補全(糾錯)**的功能

查詢推薦須要注意的點app

  • 編輯距離
    • 測量拉丁文的類似度
  • 編輯操做
    • 替換一個字符 (編輯距離加一)
    • 插入一個字符
      • 只有一個增長一個字符 編輯距離+1
      • 兩個同事增長一個字符 若是相等編輯距離不變若是不等編輯距離+1
    • 刪除一個字符

下邊拿兩個單詞來進行舉例搜索引擎

字符串A:kobbespa

字符串B: kobecode

表格裏邊記錄的是兩個字符串的編輯距離遞歸

- - -空串B- -k- -o- -b- e
空串A 編輯距離0 (增長一個字符編輯距離+1)1 2 3 4
k 1 min(2,2,0)=0 min(3,1,2)=1 min(4,2,3)=2 min(5,3,4)=3
o 2 min(1,3,2)=1 min(2,2,0) = 0 min(3,1,2)=1 min(4,2,3)=2
b 3 min(2,4,3) = 2 min(1,3,2) = 1 min(2,2,0)=0 min(3,1,2)=1
b 4 min(3,5,4) =3 min(2,4,3)=2 min(1,3,2) =1 min(2,2,1)=1
e 5 min(4,6,5) =4 min(3,5,4)=3 min(2,4,3)=2 min(2,3,1) =1

如圖所示最優解就爲1索引

狀態轉移方程字符串

i == 0 和 j==0 這裏就不作贅述。

i>0 和 j>0 的狀況。

d[i,j] = min(d[i,j+1] + 1 , d[i+1,j]+1 , d[i,j] + r(i,j) ). {添加的字符相等 r(i,j) = 0,不然r(i,j)=1}

代碼以下:

// 實現狀態轉移方程
		// 請注意因爲 Java 語言實現的關係,代碼裏的狀態轉移是從 d[i, j] 到 d[i+1, j+1],而不是從 d[i-1, j-1] 到 d[i, j]。本質上是同樣的。
		for (int i = 0; i < a.length(); i++) {
			for (int j = 0; j < b.length(); j++) {
				
				int r = 0;
				if (a.charAt(i) != b.charAt(j)) {
					r = 1;
				} 
				
				int first_append = d[i][j + 1] + 1;
				int second_append = d[i + 1][j] + 1;
				int replace = d[i][j] + r;
				
				int min = Math.min(first_append, second_append);
				min = Math.min(min, replace);
				d[i + 1][j + 1] = min;
				
			}
		}
		
		return d[a.length()][b.length()];
				
	}

}

複製代碼
2.2 錢幣組合的最優解

假設有 三種幣種 2,5,7 求這三種幣種組成 100 元 用的最小的紙幣張數。

方程以下:

c[totalMoney] = c[totalMoney - moneyKind()] + 1;

代碼以下:

private static int totalNumberForMoney(int[] moneyKind,int total){
        //初始化 c數組
        int[] c = new int[total+1];
        for(int i=1;i<c.length;i++){
            c[i] = -1;
        }
        c[0] = 0;
        for(int i=1;i<=total;i++){
             int[] data = new int[moneyKind.length];
              for(int j = 0;j<moneyKind.length;j++){
                  if((i - moneyKind[j])<0){
                      data[j]= -1;
                      continue;
                  }
                  data[j] = c[i - moneyKind[j]];
              }
              int min = min(data);
              if(min == -1){
                  continue;
              }
              c[i] = min + 1;
            System.out.println(i + "min" + c[i]);
        }
        return c[total];
    }

    private static int min(int[] data) {
        boolean flag = true;
        int min = -1;
        for(int i=0;i<data.length;i++){
            if(data[i]==-1){
                continue;
            }
            if(flag){
                min = data[i];
                flag = false;
                continue;
            }
            if(data[i]<min){
                min = data[i];
            }
        }
        return min;
    }
複製代碼

3.總結

動態規劃的適用場景:

**最小值,最大值,最優解,最段子串,最長子串.....**等等

解決動態規劃問題的關鍵就是寫出 問題轉移的方程,而後轉換成程序。

並且動態規劃的時間複雜度 爲mn 若是相同的問題使用遞歸循環(排列組合)進行解的話,考慮的各類複雜的狀況須要窮舉出全部的可能隨着數據量的增長時間複雜度要比mn大的多。

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息