深入理解動態(tài)規(guī)劃的一系列問題(5)
今天主要面對的問題還是路徑問題,回顧最短路的Floyd-Warshall算法,決定還是這里把它實現(xiàn)以下。經(jīng)過前面的訓(xùn)練,當(dāng)我們確定一個問題可用動態(tài)規(guī)劃方法求解時,最重要的一步就是要先給出狀態(tài)定義,其后就可以列出DPFE方程了。那么對于FW算法所求解的全路徑最短路問題,問題是要求解一個有向圖中的所有節(jié)點之間的最短路徑。也就是說對于一個N個節(jié)點的圖,總共有N(N-1)/2個可能組合,求解他們的最短路徑。對于這時的狀態(tài)定義,我們可以參考SPC問題,我們可以定義一個狀態(tài)(k,p,q)表示從p到q的最短路徑,其中k表示不超過k段組成。也就是從p到q不超過k段路徑的組合中,最短路徑的狀態(tài)。于是,轉(zhuǎn)移方程也就可以列出來了:
F(k,p,q) = min r∈S{b(p, r)+F(k?1,r,q)},k>0。其中當(dāng)p=q時,F(xiàn)(0,p,q)=0,當(dāng)p≠q時,F(xiàn)(0,p,q)=∞,b(p,p)=0,b是路徑長度函數(shù)。
這樣,列出方程,我們可以輕松寫遞歸代碼求解問題了。
當(dāng)然這里還是補(bǔ)充一下Floyd-Warshall算法的狀態(tài)轉(zhuǎn)移方程:F(k,p,q) = min{F(k?1,p,q),F(k?1,p,k)+F(k?1,k,q)},其中當(dāng)p=q時,F(xiàn)(0,p,q)=0,當(dāng)p≠q時,F(xiàn)(0,p,q)=b(p,q)。可以看出兩者的差異,F(xiàn)W算法縮減了SPC問題求解方法的中間變量r,也就是說每次求解min值不需要在一個狀態(tài)集合里尋求最短,而把min縮小到(k-1,p,q)和(k-1,p,k)+(k-1,k,q)中,這樣直接把計算復(fù)雜度降了一個量級。
遞歸Java source code:
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: public class APSP {
19:
20: private static final int INF = Integer.MAX_VALUE;
21:
22: // nodes (s,x,y,t) = {0,1,2,3}, so (s,x) = 3 means d[0][1] = 3
23: private static int[][] distance = {
24: { INF, 5, 3, INF },
25: { INF, INF, 2, 5 },
26: { INF, 1, INF, 8 },
27: { INF, INF, INF, INF }
28: };
29:
30: private static int maxNodeIndex = distance.length-1;
31:
32: private static int[] possibleSuccessors = { 0, 1 };
33:
34: public static double f(int k, int p, int q) {
35: if (k == 0 && p == q)
36: return 0;
37: if (k == 0 && p != q)
38: return distance[p][q];
39: double min = Double.MAX_VALUE;
40: for (int d : possibleSuccessors) {
41: double t = (1 - d) * f(k - 1, p, q) + d * f(k - 1, p, k) + d
42: * f(k - 1, k, q);
43: if (t < min)
44: min = t;
45: }
46: return min;
47: }
48: /**
49: * @param args
50: */
51: public static void main(String[] args) {
52: System.out.println(f(maxNodeIndex,0,3));
53: }
54:
55: }
posted on 2014-04-08 10:30 changedi 閱讀(1661) 評論(11) 編輯 收藏 所屬分類: 算法