深入理解動態規劃的一系列問題(4)
第四個動態規劃問題是 最優分配問題(Optimal Allotment Problem:ALLOT),其問題描述是:有M個單位的資源,有N個人,把d個單位的資源分配給某個人有一定的成本,如何分配這些資源給這N個人,能使成本最小。這顯然是一個典型的DP問題,組合優化策略,解決這個問題,首先就是要抽象DPFE動態規劃方程,假設M個單位的資源,N個人,把d個單位資源分配給編號為k的人的成本計算方式為C(k,d),0≤d≤M,1≤k≤N。回想我們列DPFE方程的思路,首先要想到的就是狀態,如何定義一個狀態,狀態總是針對總體,總共就M個單位的資源,N個人,那么我們不妨定義狀態(k,m),其中k為已經分配到第k個人,m為此時所剩余的資源單位。于是把這個過程擴展,以k為分析點,此時對下一個人進行d個單位資源的分配,于是對于下一個過程,就應該是第k+1個人,總共剩余m-d個單位的資源,表示為狀態(k+1,m-d)。這樣,我們的DPFE也就初現端倪了:f(k,m)=min{C(k,d)+f(k+1,m-d)}。目標函數是計算f(1,M),基本條件是f(N+1,m)=0當m≥0。
我們把問題具體化,有4個蘋果,要分給3個小朋友,小朋友按照1-3編號,每個小朋友拿到一定個數蘋果后會哭鬧一段時間(因為他們是小朋友,所以會哭鬧),具體時間表如下:
C(k,d)=[
∞,1.0,0.8,0.4,0.0
∞,1.0,0.5,0.0,0.0
∞,1.0,0.6,0.3,0.0
], 1≤k≤3, 0≤d≤4
k是小朋友編號,d是分給小朋友的蘋果數,可以看到,當分給小朋友0個蘋果時(不分蘋果),那么小朋友會無休止的哭鬧,而把全部(4個)蘋果全部分給一個小朋友時,小朋友不會哭鬧(0時間)。那么根據這個時間,提供一個最優的分蘋果方案,使得小朋友們拿到蘋果后的哭鬧時間最短。
那么,根據這個具體問題,我們抽象的結果就是f(1,4)=1.0+0.5+1.0=2.5,最優分布是d1=1.0,d2=0.5,d3=1.0,這樣的分配方案。具體解法見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: import java.util.HashMap;
19: import java.util.Map;
20:
21: public class ALLOT {
22:
23: private static int N = 3;
24: private static int M = 4;
25:
26: private static final double INF=Double.MAX_VALUE;
27:
28: private static Map<Integer,Integer> choices = new HashMap<Integer,Integer>();
29:
30: private static final double [][] c = {
31: {INF,1.0,0.8,0.4,0.0},
32: {INF,1.0,0.5,0.0,0.0},
33: {INF,1.0,0.6,0.3,0.0}
34: };
35:
36: private static double cost(int k, int d) {
37: return c[k-1][d];
38: }
39:
40: public static double f(int k, int m){
41: if(k>N&&m>=0) return 0.0;
42: else{
43: double mm = Double.MAX_VALUE;
44: int dispatch = -1;
45: for(int d=0;d<=m;d++){
46: double t = cost(k,d)+f(k+1,m-d);
47: if(t<mm) {
48: mm = t;
49: dispatch = d;
50: }
51: }
52: if(!choices.containsKey(k))
53: choices.put(k, Integer.MAX_VALUE);
54: if(mm<choices.get(k))
55: choices.put(k,dispatch);
56: return mm;
57: }
58: }
59: /**
60: * @param args
61: */
62: public static void main(String[] args) {
63: double minCost = f(1,M);
64: System.out.println("min cost is : "+minCost);
65: System.out.print("solution is : ");
66: for(int i=1;i<=N;i++){
67: System.out.print(choices.get(i));
68: if(i<N)
69: System.out.print(",");
70: }
71: }
72:
73: }
PS:因為考慮到這里的選擇不是很長的代碼,可能不影響理解DP,所以把記錄選擇方案的代碼也加進來了。
posted on 2014-04-01 11:09 changedi 閱讀(1831) 評論(4) 編輯 收藏 所屬分類: 算法