百度之星試題每周一練


百度之星,是全球最大的中文搜索引擎,百度公司面向中國高校學生和編程愛好者所舉辦的高水平的程序設計大賽。他所考試的題目,全部都是算法的題目。

鄙人雖然是一個.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).二、還有一個錯誤,你找的到嗎?

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM