昨天突然在网上看到这个智力题, 以下为分析以及程序实现过程.
智力题原题:
小明和小强都是张老师的学生,张老师的生日是M月N日?
小明和小强都是张老师的学生,张老师的生日是M月N日,2人都有知道张老师和生日是下列10组中的一天,张老师把M值告诉了小明,把N值告诉了小强,张老师问他们知道他的生日是那一天?
3月4日 3月5日 3月8日 6月4日 6月7日
9月1日 9月5日 12月1日 12月2日 12月8日
小明说:如果我不知道的话,小强肯定也不知道
小强说:本来我也不知道,但现在我知道了
小明说;哦,那我也知道了
条件一: 小明说: 如果我不知道的话,小强肯定不知道.
分析: 此句话可以说明两点,第一点,张老师对应的生日的N在以上日期中不能是唯一,纵观以上日期,生日的N可能取值:4,5,8,4,7,1,5,1,2,8. 依此看,N不能为2与7. 另外,还可以排队N为2与7所对应的月份. 因为当张老师的生日的M为6或12时,小强是可能知道生日的,与已知条件相违背.
终上条件一可以得出: 单独的N所对应的月份的所有生日都将排除. 也就是说,6月与12月的生日都将排队
条件二: 小强说:本来我不知道,但现在我知道了
分析: 根据条件一排除的日期看,现在生日的N应该是单一的.
终上条件二可以得出: 重复的N所对应的生日应该排除
条件三: 哦,那我也知道拉
分析: 根据条件二的结果,现在可以确认生日对应的M应该是单一的. 此时日期也将被确定
终上条件三可以得出: 单一的M值可能成为张老师的生日
以上为分析过程式,如何用程序来实现呢? 程序实现的过程主要是对三个条件进行处理.
程式处理: 1: 删除单独的N所对应月份的所有生日
2: 删除重复的N所对应的生日
3: 删除重复的M所对应的生日
程序代码如下:
生日对象:
2 {
3 public Birthday()
4 {
5
6 }
7 public int Month
8 {
9 get ;
10 set ;
11 }
12 public int Day
13 {
14 get ;
15 set ;
16 }
17 public override string ToString()
18 {
19 return Month + " 月 " + Day + " 日 " ;
20 }
21 }
初始化参数:
2 {
3 new Birthday { Month = 3 , Day = 4 },
4 new Birthday { Month = 3 , Day = 5 },
5 new Birthday { Month = 3 , Day = 8 },
6 new Birthday { Month = 6 , Day = 4 },
7 new Birthday { Month = 6 , Day = 7 },
8 new Birthday { Month = 9 , Day = 1 },
9 new Birthday { Month = 9 , Day = 5 },
10 new Birthday { Month = 12 , Day = 1 },
11 new Birthday { Month = 12 , Day = 2 },
12 new Birthday { Month = 12 , Day = 8 },
13 };
14 private static int [] SinDays = new int []{ 2 , 7 };
入口方法:
2 {
3 ConditionOne();
4 ConditionTwo();
5 ConditionThree();
6 if (ListBirthday.Count == 0 )
7 {
8 Console.WriteLine( " 给出的条件有误,请确认 " );
9 Console.Read();
10 return ;
11 }
12 foreach (Birthday bd in ListBirthday)
13 {
14 Console.WriteLine(bd.ToString());
15 }
16 Console.Read();
17 }
条件一处理逻辑:
2 {
3 List < Birthday > DelBirthday = new List < Birthday > ();
4 List < int > DelMonths = new List < int > ();
5 // 根据独立天,查找对应的月份,并放入 DelMonths中
6 foreach (Birthday bd in ListBirthday)
7 {
8 for ( int i = 0 ; i < SinDays.Length; i ++ )
9 {
10 if (bd.Day == SinDays[i])
11 {
12 if ( ! DelMonths.Contains(bd.Month))
13 {
14 DelMonths.Add(bd.Month);
15 }
16 break ; // Break 终止循环 因为一个日期不会存在两天. 终止循环后可以减少循环次数
17 }
18 }
19 }
20 // 根据月份,查询将要删除的日期. 并放入 DelBirthday中
21 foreach (Birthday bd in ListBirthday)
22 {
23 foreach ( int TempM in DelMonths)
24 {
25 if (bd.Month == TempM)
26 {
27 DelBirthday.Add(bd);
28 break ; // 与上同理
29 }
30 }
31 }
32 // 删除日期
33 foreach (Birthday bd in DelBirthday)
34 {
35 ListBirthday.Remove(bd);
36 }
37 }
条件二处理逻辑:
2 /// 小强说:刚才我不知道,但现在我知道了
3 /// 分析:由条件一得出的结果,现在小强知道的天应该是集合中单一的天.
4 /// 固: 除去重复的天
5 /// </summary>
6 static void ConditionTwo()
7 {
8 List < Birthday > DelDays = new List < Birthday > ();
9 List < int > TempDays = new List < int > ();
10 List < int > TempDays1 = new List < int > ();
11 foreach (Birthday bd in ListBirthday)
12 {
13 if ( ! TempDays.Contains(bd.Day))
14 {
15 TempDays.Add(bd.Day);
16 }
17 else
18 {
19 TempDays1.Add(bd.Day);
20 }
21 }
22 foreach (Birthday bd in ListBirthday)
23 {
24 foreach ( int Num in TempDays1)
25 {
26 if (bd.Day == Num)
27 {
28 DelDays.Add(bd);
29 break ;
30 }
31 }
32 }
33 // 删除日期
34 foreach (Birthday bd in DelDays)
35 {
36 ListBirthday.Remove(bd);
37 }
38 }
条件三处理逻辑:
2 /// 小明说,那我也知道了
3 ///
4 /// 分析: 月份不能相同
5 /// </summary>
6 static void ConditionThree()
7 {
8 List < Birthday > DelMonths = new List < Birthday > ();
9 List < int > TempMonths = new List < int > ();
10
11 List < int > TempMonths1 = new List < int > ();
12
13 foreach (Birthday bd in ListBirthday)
14 {
15 if ( ! TempMonths.Contains(bd.Month))
16 {
17 TempMonths.Add(bd.Month);
18 }
19 else
20 {
21 TempMonths1.Add(bd.Month);
22 }
23 }
24 foreach (Birthday bd in ListBirthday)
25 {
26 foreach ( int Num in TempMonths1)
27 {
28 if (bd.Month == Num)
29 {
30 DelMonths.Add(bd);
31 break ;
32 }
33 }
34 }
35 // 删除日期
36 foreach (Birthday bd in DelMonths)
37 {
38 ListBirthday.Remove(bd);
39 }
40 }
运行结果: 9月1日
源码下载地址: