编程之美-饮料供货-动态规划
题目:在微软亚洲研究院上班,大家早上来的第一件事是干啥呢?查看邮件?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 }


浙公网安备 33010602011771号