使用程序解决一道逻辑推理题
今天看朋友发了一个老问题,一道很有意思的推理题:(转载请指明出于breaksoftware的csdn博客)
小明和小强都是张老师的学生,张老师的生日是M月N日,2人都知道张老师的生日是下列10组中的一天:
3月4日 3月5日 3月8日
6月4日 6月7日
9月1日 9月5日
12月1日 12月2日 12月8日
张老师将M值告诉了小明,将N值告诉了小强,张老师问他们知道他的生日是哪一天吗?
小明说:如果我不知道的话,小强肯定不知道
小强说:本来我也不知道,但是现在我知道了
小明说:哦,那我也知道了
据上面信息,推断出张老师的生日是哪一天?
这个逻辑题,如何用程序实现?其实这是一个建模过程,我们需要用专业的术语重新描述这个逻辑。
这个问题数据只有2个:月数和天数。逻辑是参杂2个人角度看问题的3句话。我们分析这个问题时,首先要保持第三者的视角,逐个从其他两个视角去分析这个问题。然后就是建立模型,我们看这样的数据有个特征:{Key,Value}键值对。但是可以看出这是个MultiMap,即一个键可以对应多个值。
我们沿着这个思路走.可以发现,站在小明的角度,我们可以将数据建立成一个MultiMap。他眼中的数据使用月数M为键,天数N为值。以后我们称下表为“小明表”。
可以站在小强的角度,我们将数据建立成一个新的MultiMap。他眼中的数据使用天数N为键,月数M为值。以后我们称下标为“小强表”。
我们再回到第三者的角度,可以得出,这两张表对于小明和小强都是可见的。
我们将小明和小强的对话,一条一条转换为约束条件。
1 小明说:如果我不知道的话,小强肯定不知道
小明是看了“小强表”之后得出以上结论。这句话意味着:他所知的M值在“小强表”中不存在Key Value唯一对应关系。即12月2日和6月7日,这两个月份12和6都不是老师的生日月数。因为如果是M是12或6,小明在不知道N的情况下,无法给定如此“拽”的回答。于是逐步排除出一下结果(红色代表排除的选项)
2 小强说:本来我也不知道,但是现在我知道了
小强在看到上图后,得出上面结论。这个说明,小强知道的N在上表中是Key Value唯一对应关系。于是得出
因为小强知道N是多少,所以剩下的选项中,他知道正确答案了。只是我们还不知道。我们期待小明的话。
3 小明说:哦,那我也知道了
对于小明,他和我们一样,可以看到上图。于是他知道N的值只可能是1、4、8。于是修改“小明表”为
由于此时小明已经知道了答案。可以见得M值在上表中是Key Value唯一对应关系。于是我们可以排除3和12。得出
此时有两个答案。我们此时结合筛选后的“小强表”
此时,我们可以说6月4日在“小强表”中已被排除,所以我们选择9月1日。或者我们从这个两个表中找到了唯一的共同选项,从而得知是9月1日。
草编了一下代码
// ACM.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"
#include <list>
/*
小明和小强都是张老师的学生,张老师的生日是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日
小明说:如果我不知道的话,小强肯定不知道
小强说:本来我也不知道,但是现在我知道了
小明说:哦,那我也知道了
据上面信息,推断出张老师的生日是哪一天?
*/
struct stBirthday{int nMonth;int nDay;bool bMaybe;bool bMaybeSecond;bool bMaybeThird;
};static stBirthday g_BirthdayArray[] = {{3,4,false,false,true},{3,5,false,false,true},{3,8,false,false,true},{6,4,false,false,true},{6,7,false,false,true},{9,1,false,false,true},{9,5,false,false,true},{12,1,false,false,true},{12,2,false,false,true},{12,8,false,false,true},
};int g_nArrayCount = sizeof(g_BirthdayArray)/sizeof(stBirthday);typedef std::list<stBirthday> ListBirthday;
typedef ListBirthday::iterator ListBirthdayIter;void XiaoMingFirst(ListBirthday& listBirthday)
{// 小明知道月数后,说:如果我不知道,小强肯定也不知道// 这意味着小明看了他所知道月数里的每个天数在其他月数里都能找到// 于是天数具有唯一性的选项是“不可能”的for ( ListBirthdayIter it = listBirthday.begin(); it != listBirthday.end(); it++ ) {if ( it->bMaybe ) {// 该值可能在之后的逻辑中提前被设置,所以不用比较// 这个日期是存在可能的continue;}for ( ListBirthdayIter iter = it; iter != listBirthday.end(); iter++){if ( iter == it ) {// 不和自身比较continue;}if ( it->nDay == iter->nDay ) {// 第一个答案的提炼的思想就是:// 小明看了他所知道月数里的每个天数在其他月数里都能找到// 所以,没有小明的答案,小强肯定不知道确切的几月几日// 于是,我们将有天数有重复的答案认定为可能的选项it->bMaybe = iter->bMaybe = true;}}}for ( ListBirthdayIter it = listBirthday.begin(); it != listBirthday.end(); it++){if ( it->bMaybe ) {continue;}// 经过上轮处理,需要将该月里可能同时存在“可能”和“不可能”的选项的可能性都设置为“不可能”// 因为小明看了他所知道月数里的每个日数在其他月数里“都”能找到,我们要配合“都”这个必要条件for ( ListBirthdayIter iter = listBirthday.begin(); iter != listBirthday.end(); iter++){if ( it->nMonth == iter->nMonth ) {iter->bMaybe = false;}}}
}void XiaoQiangFirst(ListBirthday& listBirthday)
{// 小强分析了小明回答后,回答:本来我也不知道,但是现在我知道了// 这意味着小明的答案给小强提供了月数信息// 因为小明的回答让他在待选择的多个结果中排除了其他可能性,只有一个选择// 于是编码的思路就是:// 1 在已经“不可能”的月数中,寻找其对应的天数在“可能”的月中是否有对应关系// 或者// 2 在已经“可能”的月数中,寻找其对应的天数在“不可能”的月中是否有对应关系// 以下编码选择1思路实现for ( ListBirthdayIter it = listBirthday.begin(); it != listBirthday.end(); it++ ) {if ( it->bMaybe ) {// 寻找“不可能”的月数,于是“可能”的月数不作为可选条件continue;}for ( ListBirthdayIter iter = listBirthday.begin(); iter != listBirthday.end(); iter++){if ( false == iter->bMaybe ){// 在找到一个“不可能”的月数情况下,寻找“可能”的月数,以作下步筛选continue;}if ( it->nDay == iter->nDay ) {// 存在对应关系,则该“可能”日期经过第二轮筛选,还是“可能”的iter->bMaybeSecond = true;}}}
}void XiaoMingSecond(ListBirthday& listBirthday)
{// 小明在听到小强的回答后,说:哦,那我也知道了。// 这意味着小强的答案已经为小明提供了天数信息// 在可能众多的选项中,小明却知道了答案,// 证明信息经过小强筛选过后,小明所知道的月数中,只有一个天数答案for ( ListBirthdayIter it = listBirthday.begin(); it != listBirthday.end(); it++ ) {if ( false == it->bMaybeSecond ) {it->bMaybeThird = false;continue;}for ( ListBirthdayIter iter = it; iter != listBirthday.end(); iter++){if ( iter == it ) {// 不和自身比较continue;}if ( false == iter->bMaybeSecond || false == iter->bMaybeThird ) {// 不满足条件的不做比较continue;}if ( it->nMonth == iter->nMonth ) {// 经过两轮筛选,如果有两个选项是同一个月数的// 则可以认为该数月的所有选项都是“不可能”for ( ListBirthdayIter iterIn = it; iterIn != listBirthday.end(); iterIn++){if ( it->nMonth == iterIn->nMonth ) {iterIn->bMaybeThird = false;}}}}}
}void TestBirthday()
{ListBirthday listBirthday;for ( int n = 0; n < g_nArrayCount; n++ ) {listBirthday.push_back(g_BirthdayArray[n]);}XiaoMingFirst(listBirthday);printf("The First Result:\n");for ( ListBirthdayIter it = listBirthday.begin(); it != listBirthday.end(); it++ ) {if ( it->bMaybe ){printf("Month:%d Day:%d\n", it->nMonth, it->nDay);} }XiaoQiangFirst(listBirthday);printf("The Second Result:\n");for ( ListBirthdayIter it = listBirthday.begin(); it != listBirthday.end(); it++ ) {if ( it->bMaybeSecond ){printf("Month:%d Day:%d\n", it->nMonth, it->nDay);} }XiaoMingSecond(listBirthday);printf("The Third Result:\n");for ( ListBirthdayIter it = listBirthday.begin(); it != listBirthday.end(); it++ ) {if ( it->bMaybeThird ){printf("Month:%d Day:%d\n", it->nMonth, it->nDay);} }
}int _tmain(int argc, _TCHAR* argv[])
{TestBirthday();return 0;
}

相关文章:

AjaxControlToolKit之DragPanelExtender用法
1、将控件ToolkitScriptManager拖至页面中...2、定义3个Panel,用于实现窗体拖动效果,代码如下:1<body>2<form id"form1"runat"server">3<div>4<cc1:ToolkitScriptManager ID"ToolkitScriptMan…
自带数据线的迷你数显充电宝,旅途必备
还有20多天就过年了有件极其考验情商的事情也来临了就是我们这群90后过年最怕的事情——相亲但是在尴尬的场合手机可是一个缓解气氛的好东西不管是想要选择看电影,还是找附近的游玩只要有手机,就可以从容不迫的应对但是带手机最尴尬的事情莫过于结账的时…

SpringJDBC的简单应用
此处写上应用JdbcTemplate的dao操作数据库的一些代码(含基本的增删改查,注:重点是查询出多条语句的写法): package org.sakaiproject.zhaorui.dao.impl;import java.sql.ResultSet;import java.sql.SQLException;impor…

WMI技术介绍和应用——查询硬件信息
这个月实在太忙了,一直没有时间去继续写WMI的应用例子。 本来是希望将《WMI技术介绍和应用》系列博文写的像WMI百科全书般,但是貌似对这个技术感兴趣的同学并不多,所以我决定对部分知识点点到为止,有需求的同学可以查询MSDN相关类…
微软开源的自动机器学习工具上新了:NNI概览及新功能详解
作者 | 宋驰来源 | 微软研究院AI头条(ID: MSRAsia)2018年9月,微软亚洲研究院发布了第一版 NNI (Neural Network Intelligence) ,目前已在 GitHub 上获得 3.8K 星,成为最热门的自动机器学习(AutoMLÿ…

10624 - Super Number
题目链接 题意:给出n到m的范围,求出一个数在前i位数组成的数字能被i整除。假设存在输出这个数,假设不存在。输出-1. 思路:回溯,每次放第i位,然后推断是否符合题意。这题踩着时间过去的2.6s(看了…

2008找回企业久违的网速
曾几何时,单位上网访访问页面也是忽忽的,等待10秒简直是不可忍受;曾几何时,公司网络下载是嗖嗖的,转眼已是2M开外;曾几何时,办公室上网看视频是杠杠的,那流畅那画面都快赶上电视直播…

发现一个windows7(32bit或64bit)DirectUI的bug
前段时间发现一个windows7的一个bug,不是什么严重的问题,我在此记录下。(转载请指明出于breaksoftware的csdn博客) 重现步骤如下: 0 在文件夹的“更改您的视图”中选择下图中用红色叉叉标记的项 1 新建一个文件夹名为“Cs" 2…
阿里达摩院2020趋势第一弹:感知智能的“天花板”和认知智能的“野望”
作者 | Just出品 | AI科技大本营(ID:rgznai100)“感知智能与认知智能是相辅相成的关系。认知智能需要感知系统来进行信号处理和概念识别,而感知系统也需要认知系统的反馈来决定如何进行更有效的提取和识别。”1月2日,阿里巴巴达摩…

Java 对synchronized的补充Lock锁
Java并发编程:Lock 从Java 5之后,在java.util.concurrent.locks包下提供了另外一种方式来实现同步访问,那就是Lock。 也许有朋友会问,既然都可以通过synchronized来实现同步访问了,那么为什么还需要提供Lock࿱…
有奖评选 | 2020年的AI技术公开课,你想听到哪些干货?
CSDN技术公开课有奖评选开始啦~~听过课的小伙伴们,哪位讲师的分享让你获益匪浅?记得给TA投票哦!投票后获取入群方式,参与抽奖,奖品很丰厚哦~~进入付费时代,如今我们看似只要招招手,一切知识随手…
一个分析“文件夹”选择框实现方法的过程
在软件开发中,我们如果存在“导入导出”的场景时,难免会用到“文件夹”选择框。之前一直没有太关注过这个的实现过程。最近在工作中遇到了一些问题,我做了一些研究。在此记录下研究的过程。(转载请指明出于breaksoftware的csdn博客…

Openssl req命令
一、简介 req指令用来创建和处理PKCS#10格式的证书 二、语法 openssl req [-inform PEM|DER] [-outform PEM|DER] [-in filename] [-out filename] [-text] [-pubkey] [-noout] [-verify] [-modulus] [-nodes] [-subject] [-passin arg] [-passout arg] [-key filename] [-key…
使用windbg抓取崩溃文件和分析的过程
在软件编程中,崩溃的场景比较常见的。且说微软技术再牛X,也是会出现崩溃的场景。网上有一段Win98当着比尔盖茨蓝屏的视频非常有意思。 (转载请指明出于breaksoftware的csdn博客)我们身边的很多软件都引入了dump生成和收集机制。但…
TF 2.1.0-rc2发布,2020年停止支持Python 2
作者 | 神经星星来源 | HyperAI超神经(ID:HyperAI)【导读】2020 年 1 月 1 日,Python 2 停止维护,正式退休。Python 3 全面登场的时刻,TensorFlow 也在悄悄改变。近日 TensorFlow 官方 GitHub 账号中,发布了…

重新认识笔记本锂电池的保养
重新认识笔记本锂电池的保养 对于笔记本电脑来说,电池可以说是一个比较重要的部件,它的效能直接关系到笔记本电脑在缺少电源的环境中的工作能力。而电池在笔记本电脑的众组件中又算是一个不折不扣的消耗品,因此涉及到笔记本电脑电池的保养和合…

nginx转发及后端服务器获取真实client的IP
针对nginx的模块介绍可以查阅wiki:http://wiki.nginx.org/Modules常用模块:HTTP CoreProxyRewriteUpstream 原理:squid,varnish以及nginx等,在做反向代理的时候,因为要代替客户端去访问服务器,所以…

AJAX的组成应用
表示层XHTMLCSS 动态显示和数据 DOM (文档对象模型)数据交互和操作 XML,XSLT 异步数据获取 XMLHttpRequest 绑定和处理数据 JavaScript XMLhttpRequest对象属性:Number readyState 4 表示完成Function onreadystatechange 回调函数string responseText XMLDocument responseXM…
打开,保存文件框的文本溢出排查
工作中遇到的这个问题还是很有意思的。其中嵌套了很多奇葩性的问题。 (转载请指明出于breaksoftware的csdn博客)我们来看下故事的发生过程,QA同学发现我们存在如下的bug 看到如此多的串,可以认为这个是典型的溢出问题。后来我咨询…
2020年,为什么说入坑AI是最好的时机?
2019年可以说是AI全面落地和商用的一年,产业智能化成为各个行业重点关注的发展方向,交通、工业、农业、医疗等主流行业无一例外。随着人工智能技术的进一步发展和落地,深度学习、数据挖掘、自动程序设计等领域也将在更多应用场景中得到实现。…

IIS 伪静态配置(安装ISAPI_Rewrite配置)
第一:首先到官方网站下载ISAPI_Rewrite 我的机子是32位的就下32位免费版的,链接地址如下: http://www.helicontech.com/download/isapi_rewrite/ISAPI_Rewrite3_0064_Lite.msi 可以选择不同版本:http://www.helicontech.com/downl…
Github标星24k,127篇经典论文下载,这份深度学习论文阅读路线图不容错过
作者 | Floodsung翻译 | 黄海广来源 | 机器学习初学者(ID:ai-start-com)【导读】如果你是深度学习领域的新手,那么你可能会遇到的第一个问题是“我应该从哪篇论文开始阅读?”本文就是一篇深度学习论文的阅读路线图!该…

c/c++面试
1. static在c,c中有什么不同点2. 堆和栈的区别3. 纯虚函数4. 指针和引用的区别5. 如果构造函数出错,如何处理?6. 对设计模式是否熟悉,用过哪些?7. c如何使用c中的函数,为什么?整理:1…

一种解决启动进程传递参数过长的方法
工作中,QA同学在测试我们程序的时候,发现在XP下,我们的A进程无法启动我们的B进程。而在Win7 64bit系统下功能正常。RD同学调试后,发现我们A进程中使用ShellExcute去启动了B进程(转载请指明出于breaksoftware的csdn博客…

Ubuntu“无法获得锁\加锁”解决方案
2019独角兽企业重金招聘Python工程师标准>>> 当你添加了源,更新源的时候,如果中途中断了更新,安装软件或者再次更新的时候就是出现如下提示, E: 无法获得锁 /var/lib/apt/lists/lock – open (11: 资源暂时不可用) E: …

一步一步学Silverlight 2系列(3):界面布局
概述 Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言Visual Basic, Visual C#, IronRuby, Ironpython,对JSON、Web Service、WCF以及Sockets的支持等一系列新的特性。《一步一步学Silverlig…

一种准标准CSV格式的介绍和分析以及解析算法
CSV是一种古老的数据传输格式,它的全称是Comma-Separated Values(逗号分隔值)。出生在那个标准缺失的蛮荒年代,CSV的标准一直(到2005年)是NULL——世间存在着N种CSV格式,它们自成体系࿰…
新战场路在何方——详解360金融数据中台之旅
作者 |360金融架构总监黄建庭出品 | AI科技大本营(ID:rgznai100)本文为CSDN即将推出的《新战场:决胜中台》专刊的第 4 篇文章。自阿里巴巴引入中台概念后,市场对中台的关注度持续“高烧”不退。作为企业的基础平台,数据…

oracle中的exists 和not exists 用法详解
有两个简单例子,以说明 “exists”和“in”的效率问题 1) select * from T1 where exists(select 1 from T2 where T1.aT2.a) ; T1数据量小而T2数据量非常大时,T1<<T2 时,1) 的查询效率高。 2) select * from T1 where T1.a in (select…

现代内存编号解读(转)
现代SDRAM、DDR SDRAM、DDR2 SDRAM三种主流内存颗粒的编号一、DDR SDRAM:HYNIX DDR SDRAM颗粒编号:HY XX X XX XX X X X X X X X — XX X1 2 3 4 5 6 7 8 9 10 11 12 — 13 14整个DDR SDRAM颗粒的编号,一共是由14…