百度之星试题每周一练

百度之星,是全球最大的中文搜索引擎,百度公司面向中国高校学生和编程爱好者所举办的高水平的程序设计大赛。他所考试的题目,全部都是算法的题目。

鄙人虽然是一个.net程序员,在工作之余,喜爱算法。 这个问题与现实的需求蛮贴近,故而分享给大家,我想到两种方法,提供大家,希望对大家起了一个开阔思路的作用。

首先,题意是这样的:

  1 饭团的烦恼 
  2 
  3 “午餐饭团“是百度内部参与人数最多的民间组织。 
  4 
  5 同一个部门的,同一间大学的,同一年出生的,用同一种型号电脑的,员工们总是以各种理由,各种借口组织各种长久的,临时的饭团。 
  6 
  7 参加饭团,不仅可以以优惠的价格尝到更加丰富的菜式,还可以在吃饭的时候和同事们唠唠嗑,吹吹水,增进感情。 
  8 
  9 但是,随着百度的员工越来越多,各个饭团的管理随即变得烦杂。特别是为了照顾员工们越来越挑剔的胃口,饭团的点菜负责人背负的责任越来越大。现在,这个重担落在百度之星的肩上,因为,你们将要为所有的百度饭团设计一个自动点菜的算法。 
 10 
 11 饭团点菜的需求如下: 
 12 
 13 1. 经济是我们要考虑的一个因素,既要充分利用百度员工的午餐补助,又不能铺张浪费。因此,我们希
 14 
 15 望最后的人均费用越接近 12 元越好。 
 16 
 17 2. 菜式丰富是我们要考虑的另一个因素。为简单起见,我们将各种菜肴的属性归结为荤菜,素菜,辛辣,
 18 清淡,并且每个菜只能点一次。 
 19 
 20 3. 请紧记,百度饭团在各大餐馆享受 8 折优惠。 
 21 
 22 输入数据描述如下: 
 23 
 24 第一行包含三个整数 N,M,K(0<=16,0<N<=16,0<=N,0<M<=N,0<=12),分别表示菜单上菜的数目,饭团
 25 需要点的菜的数目,就餐的人数。<K<=12),分别表示菜单上菜的数目,饭团需要点的菜的数目,就餐的
 26 人数。 
 27 
 28 紧接着 N 行,每行的格式如下: 
 29 
 30 菜名(长度不超过 20 个字符) 价格(原价,整数) 是否荤菜(1 表示是,0 表示否) 是否辛辣(1 表示
 31 是,0 表示否)例: 
 32 
 33 水煮鱼 30 1 1 
 34 
 35 紧接着是 a b c d 四个整数,分别表示需要点的荤菜,素菜,辛辣,清淡菜的数目。 
 36 
 37 输出数据: 
 38 
 39 对于每一测试数据,输出数据包含 M+1 行,前 M 行每行包含一个菜名(按菜名在原菜单的顺序排序)。第
 40 M+1 行是人均消费,结果保留两位小数。 
 41 
 42 说明: 
 43 
 44 1.结果菜单的数目应该恰好为 M,荤菜,素菜,辛辣,清淡菜的数目恰好为 a,b,c,d。在满足这样的
 45 前提下,选择人均消费最接近 12 元的点菜方案。题目数据保证有且仅有一个解。 
 46 
 47 2.每组测试数据的结果用一个空行隔开。末尾不要有多余的空行。 
 48 
 49 输入样例 
 50 
 51 3 2 2 
 52 
 53 水煮鱼 30 1 
 54 
 55 1 口水鸡 18 1 1 
 56 
 57 清炖豆腐 12 0 0 
 58 
 59 望最后的人均费用越接近 12 元越好。 
 60 
 61 2. 菜式丰富是我们要考虑的另一个因素。为简单起见,我们将各种菜肴的属性归结为荤菜,素菜,辛辣,
 62 清淡,并且每个菜只能点一次。 
 63 
 64 3. 请紧记,百度饭团在各大餐馆享受 8 折优惠。 
 65 
 66 输入数据描述如下: 
 67 
 68 第一行包含三个整数 N,M,K(0<=16,0<N<=16,0<=N,0<M<=N,0<=12),分别表示菜单上菜的数目,饭团
 69 需要点的菜的数目,就餐的人数。<K<=12),分别表示菜单上菜的数目,饭团需要点的菜的数目,就餐的
 70 人数。 
 71 
 72 紧接着 N 行,每行的格式如下: 
 73 
 74 菜名(长度不超过 20 个字符) 价格(原价,整数) 是否荤菜(1 表示是,0 表示否) 是否辛辣(1 表示
 75 是,0 表示否)例: 
 76 
 77 水煮鱼 30 1 1 
 78 
 79 紧接着是 a b c d 四个整数,分别表示需要点的荤菜,素菜,辛辣,清淡菜的数目。 
 80 
 81 输出数据: 
 82 
 83 对于每一测试数据,输出数据包含 M+1 行,前 M 行每行包含一个菜名(按菜名在原菜单的顺序排序)。第
 84 M+1 行是人均消费,结果保留两位小数。 
 85 
 86 说明: 
 87 
 88 1.结果菜单的数目应该恰好为 M,荤菜,素菜,辛辣,清淡菜的数目恰好为 a,b,c,d。在满足这样的
 89 前提下,选择人均消费最接近 12 元的点菜方案。题目数据保证有且仅有一个解。 
 90 
 91 2.每组测试数据的结果用一个空行隔开。末尾不要有多余的空行。 
 92 
 93 输入样例 
 94 
 95 3 2 2 
 96 
 97 水煮鱼 30 1 
 98 
 99 1 口水鸡 18 1 1 
100 
101 清炖豆腐 12 0 0 
102 
103 1 1 1 1 
104 
105 输出样例 
106 
107 口水鸡 
108 
109 清炖豆腐 
110 
111 12.00 
112 
113 时间要求:1S 之内

题意很长了,这么从头到尾看下来的话,令人非常的头大。我们这里用图来梳理一下相应的头绪:

那么,怎么思考这个问题了。一 在输入的情况下,我要使她的每个的菜名的字符的长度不能大于20的判断 二 输入的荤菜数 素菜数 等等 要符合输入数的总数目  三为了使其满足人均消费接近12元的目标,我这里就吧他符合点菜的每个数目的具体情况用一个键值对来保存起来,其中相应的人均消费的数目做键,而相应的点菜的情况做值。四 把比较该键值对的最小值。相应的流程图如图所示:

有了思路了,我们来看一看看他的具体的实现了.

①为了实现题意,我们需要一个菜的类相应的源代码如下:

 1 public class Cai
 2     {
 3        //名称
 4         private string _CName;
 5         public string CName
 6         {
 7             get { return _CName; }
 8             set { _CName = value; }
 9         }
10        //价格
11         public int CPrice { get; set; }
12         //是否是荤菜
13         public bool ISMeat { get; set; }
14         //是否是辣菜
15         public bool IsHot { get; set; }
16     }

实现逻辑的源代码如下:

  1             //输入具体的需求的要求
  2             Console.WriteLine(
  3                 @"第一行包含三个整数 N,M,K(0<=16,0<N<=16,0<=N,0<M<=N,0<=12),分别表示菜单上菜的数目,饭团需要点的菜的数目,就餐的人数。<K<=12),分别表示菜单上菜的数目,饭团需要点的菜的数目,就餐的人数。 
  4  紧接着 N 行,每行的格式如下: 
  5  菜名(长度不超过 20 个字符) 价格(原价,整数) 是否荤菜(1 表示是,0 表示否) 是否辛辣(1 表示
  6 是,0 表示否)例: 水煮鱼 30 1 1  
  7 紧接着是 a b c d 四个整数,分别表示需要点的荤菜,素菜,辛辣,清");
  8             Console.WriteLine(@"
  9 请输入
 10 (形如格式)
 11 3 2 2 ");
 12             //解析字符串的方法
 13             string infos = Console.ReadLine();
 14             int number1 = Convert.ToInt32(infos.Split(' ')[0]);
 15             int number2 = Convert.ToInt32(infos.Split(' ')[1]);
 16             int number3 = Convert.ToInt32(infos.Split(' ')[2]);
 17           //记录相应的菜类的泛型数组
 18             List<Cai> caisMeat = new List<Cai>();
 19             List<Cai> caisNMeat=new List<Cai>();
 20             List<Cai> caisHot=new List<Cai>();
 21             List<Cai> caisNHot=new List<Cai>();
 22             //记录比较的数组
 23             Dictionary<double,List<Cai>> lists = new Dictionary<double, List<Cai>>();
 24                 int countmeat = 0;
 25                 int countnmeat = 0;
 26                 int counthot = 0;
 27                 int countnhot = 0;
 28              //紧接着输入相应的菜数 ①
 29             for (int i = 0; i < number1; i++)
 30             {
 31                 Cai cai = new Cai();
 32                 Console.WriteLine(@"请输入格式形式
 33                              口水鸡(小于20个字) 30(价格 整数) 1(是否浑 1是 0否) 1(是否辣 1是 0否)");
 34                 infos = Console.ReadLine();
 35 
 36                 string name = infos.Split(' ')[0];
 37                 string price = infos.Split(' ')[1];
 38                 string IsMeat = infos.Split(' ')[2];
 39                 string IsHot = infos.Split(' ')[3];
 40                 if (name.Length < 20)
 41                 {
 42                     cai.CName = name;
 43                 }
 44                 else
 45                 {
 46                     i--;
 47                     continue;
 48                 }
 49                 int result;
 50                 if (int.TryParse(price, out  result))
 51                 {
 52                     cai.CPrice = Convert.ToInt32(price);
 53                 }
 54                 else
 55                 {
 56                     i--;
 57                     continue;
 58 
 59                 }
 60                 if (IsMeat == "1")
 61                 {
 62                     cai.ISMeat = true;
 63                     caisMeat.Add(cai);
 64                     countmeat++;
 65                 }
 66                 else if (IsMeat == "0")
 67                 {
 68                     cai.ISMeat = false;
 69                     caisNMeat.Add(cai);
 70                     countnmeat++;
 71                 }
 72                 else
 73                 {
 74                     i--;
 75                     continue;
 76 
 77                 }
 78                 if (IsHot == "1")
 79                 {
 80                     cai.IsHot = true;
 81                     caisHot.Add(cai);
 82                     counthot++;
 83                 }
 84                 else if (IsHot == "0")
 85                 {
 86                     cai.IsHot = false;
 87                     caisNHot.Add(cai);
 88                     countnhot++;
 89                 }
 90                 else
 91                 {
 92                     i--;
 93                     continue;
 94 
 95                 }
 96             }
 97             Console.WriteLine("请你输入你的格式为:");
 98             Console.WriteLine("1(荤菜) 1(素菜) 1(清单菜) 1(辣菜) ");
 99             int numbermeat = 0;
100             int numbernmeat = 0;
101             int numberhot = 0;
102             int numbernhot = 0;
103 
104 
105            //判断输入的菜品和菜的数目是否是合法的 ②
106             while (true)
107             {
108                 infos = Console.ReadLine();
109                 numbermeat = Convert.ToInt32(infos.Split(' ')[0]);
110                 numbernmeat = Convert.ToInt32(infos.Split(' ')[1]);
111                 numberhot = Convert.ToInt32(infos.Split(' ')[2]);
112                 numbernhot = Convert.ToInt32(infos.Split(' ')[3]);
113                 if (numbermeat>number2)
114                 {
115                     Console.WriteLine("你以前输入的荤菜大于所有的定菜");
116                     continue;
117                 }
118                 else if (numbermeat > countmeat)
119                 {
120                     Console.WriteLine("你以前输入的荤菜大于所有的荤菜");
121                     continue;
122                 }
123                 else if (numbernmeat>number2)
124                 {
125                     Console.WriteLine("你以前输入的素菜大于所有的定菜");
126                     continue;
127                 }
128                 else if (numbernmeat > countnmeat)
129                 {
130                     Console.WriteLine("你以前输入的素菜菜大于所有的素菜");
131                     continue;
132                 }
133                 else if (numberhot>number2)
134                 {
135                     Console.WriteLine("你以前输入的辣菜大于所有的定菜");
136                     continue;
137                 }
138                 else if (numberhot>counthot)
139                 {
140                     Console.WriteLine("你以前输入的辣菜大于所有的辣菜");
141                     continue;
142                 }
143                 else if (numbernhot > number2)
144                 {
145                     Console.WriteLine("你以前输入的清淡菜菜大于所有的定菜");
146                     continue;
147                 }
148                 else if (numbernhot > countnhot)
149                 {
150                     Console.WriteLine("你以前输入的清淡菜大于所有的清淡菜");
151                     continue;
152                 }
153                 else
154                 {
155                     break;
156                 }
157             }
158  
159             int sum = 0;
160             List<Cai> temps = new List<Cai>();
161             List<Cai> temp1=new List<Cai>();
162            //判断了某个条件的样式的搭配 来放入到键值对中去③
163             for (int i = 0; i <=number1-counthot; i++)
164             {
165                
166 
167                 for (int j = 0; j <=number1-countnhot; j++)
168                 {               
169 
170                     for (int k = 0; k <= number1-countnmeat; k++)
171                     {          
172 
173                         for (int l = 0; l <= number1-countmeat; l++)
174                         {     
175                             temps=new List<Cai>();
176                             temps.AddRange(caisHot.Where(p => p.IsHot == true).OrderBy(p => p.CPrice).Skip(i).Take(numberhot).ToList());
177                             temps.AddRange(caisNHot.Where(p => p.IsHot == false).OrderBy(p => p.CPrice).Skip(j).Take(numbernhot).ToList());
178                              temps.AddRange(caisNMeat.Where(p => p.ISMeat == false).OrderBy(p => p.CPrice).Skip(k).Take(numbernmeat).ToList());
179 
180                             temps.AddRange(caisMeat.Where(p => p.ISMeat == true).OrderBy(p => p.CPrice).Skip(l).Take(numbermeat).ToList());
181 
182                             temps = temps.Distinct().ToList();
183                             if (!lists.Keys.Contains(temps.Sum(p => p.CPrice) * 0.8 / number3))
184                             {
185                                 temp1 = temps;
186 
187                                 lists.Add(Convert.ToDouble(temps.Sum(p => p.CPrice))*0.8/number3, temp1);
188                             }
189 
190                         }
191                     }
192                 }
193             }
194            //找出最接近人均12元的 菜品的搭配④
195             double min = Math.Abs(lists.Keys.First()-12);
196             double keys = lists.Keys.First();
197             foreach (var list in lists.Keys)
198             {
199                 if (Math.Abs(list-12)<min)
200                 {
201                     min = Math.Abs(list - 12);
202                     keys = list;
203                 }
204             }
205           //按照格式的输出            
206 Console.WriteLine("-------名称------价格---------是否辛辣-----------是否荤菜-------------");
207             foreach (var list in lists[keys])
208             {
209                 Console.WriteLine(string.Format("------{0}----{1}------------------{2}-------------{3}-----------", list.CName, list.CPrice, list.IsHot ? "" : "", list.ISMeat ? "" : ""));
210             }
211            
212             Console.WriteLine(string.Format("--------------人均消费:{0}------------", keys));
213             Console.ReadKey();
214 
215         }

①输入菜的数目,计算各种素菜数目,荤菜数目,辣菜数目,清淡菜数目,把其各种菜品的菜添加到泛型数目中。

②输入荤菜,素菜,辣菜,清淡菜的数目,判断他是否满足相应的总菜的数目。

③将每种满足的菜式放入泛型数组中,计算相应的人均数目,放入键值对。

④ 计算相应键值对最接近12元的键, 将其对应的键的值输出,就满足题意。

最终,运行结果,效果如下:

这就是我的一点点的想法,还有很多不够。一、他中时间算法复杂度是o(n^4).二、还有一个错误,你找的到吗?

 

posted on 2012-12-11 11:03  laozhu1124  阅读(2506)  评论(3编辑  收藏  举报

淘宝免费计数器