深入理解动态规划的一系列问题(4)

深入理解动态规划的一系列问题(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,所以把记录选择方案的代码也加进来了。



你可能感兴趣的:(深入理解动态规划的一系列问题(4))