张老师的生日问题-C#算法实现

小明和小强都是张老师的学生,张老师的生日是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日
小明说:如果我不知道的话,小强肯定也不知道
小强说:本来我也不知道,但是现在我知道了
小明说:哦,那我也知道了
请根据以上对话推断出张老师的生日是哪一天??

相信很多朋友都看过这个逻辑推理题吧,正确的答案是9月1日,推理过程我这里就不在再说了,Google一下一大堆,我要说的是用C#来得到这个推理结果^_^

更新:评论中有网友质疑答案,我的推理过程是这样的:

1。分析所有生日集合,月份有{3,6,9,12},日有{4,5,8,7,1,5,2}。

2。小明说:“如果我不知道的话,小强肯定也不知道”,在日的集合中,{2,7}只出现一次。小明会这样说,那就可以推出小明得到的M不是{6,12}。因为小强的N值是{2,7}的话,他可以直接得到张老师的生日,小明的M值就没有意义了。而小明这样说了,那就说明小明手中的M不是{6,12}。

3。小强说:“本来我也不知道,但是现在我知道了”。扣除M={6,12},剩下可能的为{{3,4},{3,5},{3,8},{9,1},{9,5}}小强说他知道了,由于小强只知道N,而他能肯定得到张老师的生日,所以他的N值一定是剩下集合中日数唯一的。这就可以排除{{3,5},{9,5}}了。

4。小明说:“哦,那我也知道了”。小明的是月份,剩下集合是{{3,4},{3,8},{9,1}},如果小明的M是3,那就有两个日期可以选择,不能确定生日。既然小明能确定张老师的生日,那小明手中的M就是9。

所以张老师的生日是:9月1日。

下面的代码也是照着这个思路来写的。

原文地址:http://blog.moozi.net/archives/2008/12/05/using-c-sharp-solve-the-problem-of-mr-zhangs-birthday/

请看我的演示代码

class Program   
{   
    
/// <summary>   
    
/// 小明和小强都是张老师的学生,张老师的生日是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日   
    
/// 小明说:如果我不知道的话,小强肯定也不知道   
    
/// 小强说:本来我也不知道,但是现在我知道了   
    
/// 小明说:哦,那我也知道了   
    
/// 请根据以上对话推断出张老师的生日是哪一天??   
    
///   
    
/// Author     :  木子   
    
/// CopyRight:  http://blog.moozi.net   
    
/// </summary>   
    
/// <param name="args"></param>   

    static void Main(string[] args)   
    
{   
        Dictionary
<intint[]> birthdays = new Dictionary<intint[]>();   
        birthdays.Add(
1,new int[]{3,4});   
        birthdays.Add(
2,new int[]{3,5});   
        birthdays.Add(
3,new int[]{3,8});   
        birthdays.Add(
4,new int[]{6,4});   
        birthdays.Add(
5,new int[]{6,7});   
        birthdays.Add(
6,new int[]{9,1});   
        birthdays.Add(
7,new int[]{9,5});   
        birthdays.Add(
8,new int[]{12,1});   
        birthdays.Add(
9,new int[]{12,2});   
        birthdays.Add(
10,new int[]{12,8});   
  
        AnalyseBirthday(birthdays);            
  
        
if (birthdays.Keys.Count > 0)   
        
{   
            
foreach (KeyValuePair<intint[]> item in birthdays)   
            
{   
                Console.WriteLine(
"张老师可能的生日为:{0}月{1}日", item.Value[0], item.Value[1]);   
            }
   
        }
   
        
else  
        
{   
            Console.WriteLine(
"无解");   
        }
   
        Console.ReadLine();   
    }
        
  
    
private static void AnalyseBirthday(Dictionary<intint[]> birthdays)   
    
{   
        
//days:所有N值集合,TKey:是N值,TValue:是出现次数   
        Dictionary<intint> days = new Dictionary<intint>();   
        
//months:所有N值集合,TKey:是M值,TValue:是出现次数   
        Dictionary<intint> months = new Dictionary<intint>();   
  
        
//遍历birthdays并分别对days,months赋值   
        foreach (KeyValuePair<intint[]> item in birthdays)   
        
{   
            
if (days.ContainsKey(item.Value[1]))   
                days[item.Value[
1]] += 1;   
            
else  
                days.Add(item.Value[
1], 1);   
            
if (months.ContainsKey(item.Value[0]))   
                months[item.Value[
0]] += 1;   
            
else  
                months.Add(item.Value[
0], 1);   
        }
   
  
        
//声明一个临时用的List:tempDays,用来存储N值   
        List<int> tempDays = new List<int>();   
        
//声明一个临时用的List:tempMonths,用来存储M值   
        List<int> tempMonths = new List<int>();   
        
//声明一个临时用的List:keys,用来存储birthdays的TKey值   
        List<int> keys = new List<int>();   
  
        
//查找所有可能生日中N值只出现一次的对应值,并将其保存到tempDays中   
        
//并获取到唯一N值相对应的M值,并将其保存到tempMonths中   
        foreach (KeyValuePair<intint> item in days)   
        
{   
            
if (item.Value == 1)   
            
{   
                tempDays.Add(item.Key);   
  
                
foreach (KeyValuePair<intint[]> birthday in birthdays)   
                
{   
                    
if (birthday.Value[1== item.Key)   
                    
{   
                        
if (!tempMonths.Contains(birthday.Value[0]))   
                            tempMonths.Add(birthday.Value[
0]);   
                    }
   
                }
   
            }
   
        }
   
  
        
//遍历所有可能的生日,并获取tempMonths中的所有   
        
//值在birthdays相应对应的TKey,存储到keys中   
        foreach (int month in tempMonths)   
        
{   
            
foreach (KeyValuePair<intint[]> birthday in birthdays)   
                
if (birthday.Value[0== month)   
                    keys.Add(birthday.Key);   
        }
   
  
        
//遍历keys,在birthdays移除M=key的不可能的生日   
        
//移除months中相应的值   
        
//days出现的次数减一   
        foreach (int key in keys)   
        
{   
            months.Remove(birthdays[key][
0]);   
            days[birthdays[key][
1]] -= 1;   
            birthdays.Remove(key);   
        }
   
  
        
//在days中移除不可能生日   
        foreach (int day in tempDays)   
        
{   
            days.Remove(day);   
        }
   
  
        
//清空tempDays   
        tempDays.Clear();   
        
//清空keys   
        keys.Clear();   
  
        
//遍历所有可能的生日,移除N值出现过两次的日期   
        foreach (KeyValuePair<intint> item in days)   
        
{   
            
if (item.Value > 1)   
            
{   
                tempDays.Add(item.Key);   
                
foreach (KeyValuePair<intint[]> birthday in birthdays)   
                
{   
                    
if (birthday.Value[1== item.Key)   
                    
{   
                        
if (!keys.Contains(birthday.Key))   
                            keys.Add(birthday.Key);   
                        months[birthday.Value[
0]] -= 1;   
                    }
   
                }
   
            }
   
        }
   
        
foreach (int key in keys)   
            birthdays.Remove(key);   
  
        keys.Clear();   
        tempMonths.Clear();   
  
        
//遍历所有可能的生日,移除M值出现过两次的日期   
        foreach (KeyValuePair<intint> item in months)   
        
{   
            
if (item.Value > 1)   
                
if (!tempMonths.Contains(item.Key))   
                    tempMonths.Add(item.Key);   
        }
   
        
foreach (int month in tempMonths)   
        
{   
            
foreach (KeyValuePair<intint[]> item in birthdays)   
                
if (item.Value[0== month)   
                    
if (!keys.Contains(item.Key))   
                        keys.Add(item.Key);   
        }
   
        
foreach (int key in keys)   
            birthdays.Remove(key);   
              
    }
   
}
  

 

整个过程foreach太多了,效率上有很大的问题,水平有限。还请网友不吝赐教!谢谢,嘿嘿:-)

posted @ 2008-12-05 17:52  木子博客  阅读(4665)  评论(25编辑  收藏  举报