深入理解動態規劃的一系列問題(8)
最優二叉搜索樹問題(Optimal Binary Search Tree Problem (BST))是算導上又一個經典例題,給定一系列數據項X={x0,x1,…,x(n-1)},每項都有一個訪問概率p(xi),目標是構建一棵二叉搜索樹使得訪問每個節點的成本最小,即Σ(p(xi) * level(xi))最小,而level(xi)是指xi項在樹中的深度。因為樹的遞歸特性再加二叉搜索樹的應用廣泛性使得用DP來求解這個最優化問題最合適不過。求解思路還是一樣,目標是要列出DPFE,那么第一步要理解目標并把狀態定義出來,有了狀態和執行步驟,轉移方程自然就OK了。因為面臨的是建樹的問題,所以我們的思路會自然想到,自底向上還是自頂向下?而不失一般性的一個規律是,如果是動態規劃解,多數是自頂向下,而貪心解可以做自底向上。所以我們不妨以數據項集作為狀態,即X為狀態,那么自頂向下的執行步驟將是,首先從X中選擇一個x作為節點,然后再計算去除x后的集合X’作為左右子樹……依次遞歸。于是DPFE方程為:f(X)=min a{f(Xl) + f(Xr) + r(a,X)}, X≠?,f(X)=0, X=?。其中Xl={x屬于X,且x<a}(左子樹),Xr={x屬于X,且x>a}。成本函數r(a,X)=Σp(x) x∈X。看到這個解,其實對于熟悉樹結構的人來說,這是非常直觀和自然的一個推斷結果。
以具體例子來解讀,一個數據集為{A,B,C,D,E},對應的搜索概率為{0.25,0.05,0.2,0.4,0.1}。那么最優解f(X)=f({A,B,C,D,E})=1.9,樹形為:
程序源碼:
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.SortedSet;
19: import java.util.TreeSet;
20:
21: public class BST {
22:
23: private int[] data = { 0, 1, 2, 3, 4 };// assume the n data items are
24: // the ints {0,1,..,n-1}
25: // corresponding to strings
26: // { "A", "B", "C", "D",
27: // "E"}
28: private double[] probability = { 0.25, 0.05, 0.2, 0.4, 0.1 };
29:
30: private static SortedSet<Integer> setOfAllItems = new TreeSet<Integer>();
31:
32: public BST() {
33: for (int i = 0; i < data.length; i++)
34: setOfAllItems.add(data[i]);
35: }
36:
37: private double sumOfProbabilitiesOfItems(SortedSet items) {
38: double result = 0.0;
39: for (int i = ((Integer) items.first()).intValue(); i <= ((Integer) items
40: .last()).intValue(); i++) {
41: result += probability[i];
42: }
43: return result;
44: }
45:
46: private SortedSet setOfItemsLessThanPivot(SortedSet items, int alpha) {
47: // conveniently use method headSet() from SortedSet
48: // headSet() DOES NOT include alpha
49: return new TreeSet(items.headSet(new Integer(alpha)));
50: }
51:
52: private SortedSet setOfItemsGreaterThanPivot(SortedSet items, int alpha) {
53: // conveniently use method tailSet() from SortedSet
54: // headSet() DOES include alpha
55: SortedSet ss = new TreeSet(items.tailSet(new Integer(alpha)));
56: ss.remove(alpha);
57: return ss;
58: }
59:
60: public double f(SortedSet<Integer> items) {
61: if (items.size() == 0)
62: return 0.0;
63: double min = Double.MAX_VALUE;
64: for (int a : items) {
65: double t = sumOfProbabilitiesOfItems(items)
66: + f(setOfItemsLessThanPivot(items, a))
67: + f(setOfItemsGreaterThanPivot(items, a));
68: if (t < min)
69: min = t;
70: }
71: return min;
72: }
73:
74: /**
75: * @param args
76: */
77: public static void main(String[] args) {
78: BST bst = new BST();
79: System.out.println(bst.f(setOfAllItems));
80: }
81:
82: }
posted on 2014-04-28 16:24 changedi 閱讀(1576) 評論(2) 編輯 收藏 所屬分類: 算法