Change Dir

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

          統計

          留言簿(18)

          積分與排名

          “牛”們的博客

          各個公司技術

          我的鏈接

          淘寶技術

          閱讀排行榜

          評論排行榜

          深入理解動態規劃的一系列問題(2)

          在問題1線性搜索里,我們提到了狀態轉移圖模型,因為與通用解法等價,所以基本所有動態規劃問題都可以用圖論的方法求解,很多問題等價于一個最短路徑問題。而本文主要介紹一下通俗的最短路問題——DP第二題:SPA(Shortest Path in an Acyclic Graph)。

          對于一個無環圖來講(有環圖后面講到),一個起始節點為s,一個目標節點為t,DPFE為:f(p) = min q{ b(p,q) + f(q)},其中b(p,q)是從p到q的距離,f(p)是從p到t的最短路徑,另外這里的p是q的前驅節點,如果p不是q的直接前驅,那么b(p,q)=∞。而目標函數就是求 f(s),base condition就是f(t)=0。

          那么舉例如下:一個有向無環圖,其有四個節點,集合為{s,x,y,t},五條邊,邊集合為{(s,x), (s,y), (x,y), (x,t), (y,t)},長度為{3,5,1,8,5}。那么求從s到t的最短路徑。

          image

          首先使每個節點都有到t的邊,如果沒有的,加一條虛擬邊,長度為∞,即(s,t)=∞。DPFE為:f(s) = min{b(s,x)+f(x), b(s,y)+f(y), b(s,t)+f(t)},f(x) = min{b(x,y)+f(y), b(x,t)+f(t)},f(y) = min{b(y,t)+f(t)},f(t)=0。依次代入,得到f(y)=min{5+0}=5,f(x)=min{1+5,8+0}=6,f(s)=min{3+6,5+5,∞+0}=9。

          因此最短路徑長度為9,路徑為s->x->y->t。

          代碼是經典的最短路代碼,使用鄰接矩陣來表示一個有向無環圖,這里仍然用一個遞歸函數來簡化:

             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: import java.util.HashSet;
            19: import java.util.Set;
            20:  
            21: public class ShortestPathAcyclic {
            22:  
            23:     private static final int INF = Integer.MAX_VALUE;
            24:  
            25:     // nodes (s,x,y,t) = {0,1,2,3}, so (s,x) = 3 means d[0][1] = 3
            26:     private static int[][] distance = { 
            27:         { INF, 3,      5,     INF }, 
            28:         { INF, INF, 1,     8 },
            29:         { INF, INF, INF, 5 }, 
            30:         { INF, INF, INF, INF } 
            31:     };
            32:  
            33:     private static Set<Integer> possibleNextNodes(int node) {
            34:         Set<Integer> result = new HashSet<Integer>();
            35:         for (int i = 0; i < distance[node].length; i++) {
            36:             if (distance[node][i] != INF) {
            37:                 result.add(new Integer(i));
            38:             }
            39:         }
            40:         return result;
            41:     }
            42:     
            43:     public static double f(int currentNode){
            44:         if(currentNode==3) return 0.0;
            45:         else{
            46:             Set<Integer> possibleSuccessors = possibleNextNodes(currentNode);
            47:             double min = Double.MAX_VALUE;
            48:             for(Integer d : possibleSuccessors){
            49:                 double dis = distance[currentNode][d]+f(d);
            50:                 if(dis<min) {
            51:                     min = dis;
            52:                 }
            53:             }
            54:             return min;
            55:         }
            56:     }
            57:  
            58:     /**
            59:      * @param args
            60:      */
            61:     public static void main(String[] args) {
            62:         double shortest = f(0);
            63:         System.out.println(shortest);
            64:     }
            65:  
            66: }

           

          其實這個版本的代碼沒有記錄路徑,只求出了最短距離值,路徑的記錄有很多種方式,最直觀的方法是在f函數內部的for循環結束后,把最小距離計算出的對應的后繼節點d保存,然后記錄一個(currentNode,d)這樣的一個節點對,保存到currentNode為key的一個map里,表示對應從currentNode開始到d選定的最短距離的邊,最后把map里所有這些邊都拿出來拼成一個路徑即可。具體代碼就不寫了(因為考慮到影響對動態規劃的理解,記得算法導論里也是把記錄路徑單獨寫一個函數去講解的)。

          posted on 2014-03-17 13:40 changedi 閱讀(1559) 評論(0)  編輯  收藏 所屬分類: 算法

          主站蜘蛛池模板: 随州市| 正蓝旗| 枣强县| 和田县| 民乐县| 通化县| 卢龙县| 原平市| 株洲县| 湖北省| 都江堰市| 济宁市| 鸡西市| 淄博市| 中方县| 望谟县| 荆州市| 通州市| 通江县| 英山县| 深州市| 邯郸县| 永胜县| 阳朔县| 武川县| 甘谷县| 兴文县| 安化县| 巩留县| 察雅县| 侯马市| 德昌县| 金塔县| 淅川县| 环江| 赣州市| 丁青县| 凉城县| 蓝山县| 板桥市| 正镶白旗|