编程之美-饮料供货-动态规划

    题目:在微软亚洲研究院上班,大家早上来的第一件事是干啥呢?查看邮件?No,是去水房拿饮料:酸奶,豆浆,绿茶、王老吉、咖啡、可口可乐……(当然,还是有很多同事把拿饮料当做第二件事)。
    管理水房的阿姨们每天都会准备很多的饮料给大家,为了提高服务质量,她们会统计大家对每种饮料的满意度。一段时间后,阿姨们已经有了大批的数据。某天早上,当实习生小飞第一个冲进水房并一次拿了五瓶酸奶、四瓶王老吉、三瓶鲜橙多时,阿姨们逮住了他,要他帮忙。
    从阿姨们统计的数据中,小飞可以知道大家对每一种饮料的满意度。阿姨们还告诉小飞,STC(Smart Tea Corp.)负责给研究院供应饮料,每天总量为V。STC很神奇,他们提供的每种饮料之单个容量都是2的方幂,比如王老吉,都是23=8升的,可乐都是 25=32升的。当然STC的存货也是有限的,这会是每种饮料购买量的上限。统计数据中用饮料名字、容量、数量、满意度描述每一种饮料。
    那么,小飞如何完成这个任务,求出保证最大满意度的购买量呢?
    解法:Opt[ i, j] i代表供货总容量,j代表饮料种类,假设容量都是整数,i和j都是从1开始,那么Opt[i,j]表示总容量为i的j种饮料的最大满意度。
              当只有一种饮料时,容易求得各种总容量对应的最大满意度;当新增加一种饮料时,将一部分容量用新饮料代替,求得新的满意度;
              将新的满意度与旧满意度比较,如果新结果较大就更新。
    那么Opt[i,j - 1]怎么求出Opt[i][j]呢? 将一部分容量分给第j种饮料(可能全部分完),如果第j种饮料的有K瓶,每瓶v容量,每瓶满意度是value,那么新的满意度就是Opt[i-k*v, j] + k*value
    饮料属性类:

View Code
 1     public class Beverage
 2     {
 3         public int Value;//满意度
 4         public int Volume;//每瓶的容量
 5         public int Count;//最多可提供多少瓶
 6         public Beverage(int value, int volume, int count)
 7         {
 8             Value = value;  
 9             Volume = volume;
10             Count = count;
11         }
12     }


    饮料供应:

View Code
 1     public class BeverageSupply
 2     {
 3         public int[,] Opt; //满意度数组
 4        /// <summary>
 5       /// 用动态规划算法查找最大满意度
 6       /// </summary>
 7       /// <param name="beverages">供应的所有饮料</param>
 8       /// <param name="v">总容量</param>
 9       /// <param name="t">饮料种类</param>
10       /// <returns>最优解</returns>
11         public int MaxValue(Beverage[] beverages, int v, int t) //这里可以省略t的,用beverages.Length-1表示
12         {
13             if (beverages == null || beverages.Length == 0)
14                 return -1;
15             if (v == 0)
16                 return -1;
17             if (t < 0 || t > beverages.Length) //beverages index从1开始
18                 return -1;
19             Opt = new int[v + 1, t + 1];
20             for (int j = 1; j <= t; j++)
21             {
22                 int cout = beverages[j].Count;
23                 int volume = beverages[j].Volume;
24                 int value = beverages[j].Value;
25                 for (int i = 1; i <= v; i++)    //边界条件,最大总容量
26                 {
27                     for (int k = 0; k <= cout; k++)//饮料的最大瓶数
28                     {
29                         if (i < k * volume)
30                             break;
31                         int x = Opt[i - k * volume, j - 1];
32                         int y = x + k * value;
33                         if (y >= Opt[i, j])  //如果新的饮料加进来,满意度比没加之前的同容量的大,那么替换
34                             Opt[i, j] = y;
35                     }
36                 }
37             }
38             return Opt[v, t];
39         }
40         public Beverage[] InitBeverage(int v, int t)
41         {
42             if (v < 0 || t < 0)
43                 return new Beverage[0];
44             var beverages = new Beverage[t + 1];
45             var random = new Random();
46             Console.WriteLine("满意度  容量(每瓶) 最多可提供数量(瓶)");
47             for (int i = 0; i < t; i++)
48             {
49                 //value volume count随机生成
50                 int value = random.Next(t) + 1;
51                 int volume = random.Next(v / 2) + 1;
52                 int count = random.Next(v / 2) + 1;
53                 beverages[i + 1] = new Beverage(value, volume, count);
54                 Console.WriteLine(value + "  " + volume + "  " + count);
55             }
56             return beverages;
57         }
58        
59         //打印动态规划替换的情况
60         public void MyPrint(int[,] array)
61         {
62             int cout = 0;
63             for (int row = 0; row < array.GetLength(0); row++)
64             {
65                 for (int col = 0; col < array.GetLength(1); col++)
66                 {
67                     cout++;
68                     if (cout % 10 != 0)
69                         Console.Write("{0} ", array[row, col]);
70                     else
71                         Console.WriteLine("{0} ", array[row, col]);
72                 }
73             }
74         }
75     }

    //调用

View Code
 1     static void Main(string[] args)
 2     {
 3         int t = 3;
 4         int v = 10;
 5         BeverageSupply beverageSupply = new BeverageSupply();
 6         Beverage[] beverages = beverageSupply.InitBeverage(v, t);
 7         int maxValue = beverageSupply.MaxValue(beverages, v, t);
 8         Console.WriteLine("总容量:" + v + " 最大满意度=" + maxValue);
 9         beverageSupply.MyPrint(beverageSupply.Opt);
10         Console.Read();
11     }

posted @ 2012-11-20 23:12  四龙须  阅读(546)  评论(1)    收藏  举报