P1039 侦探推理(洛谷)
昨天做了一个非常神奇的题,告诉我们做题之前一定要好好检测评测姬!
明明同学最近迷上了侦探漫画《柯南》并沉醉于推理游戏之中,于是他召集了一群同学玩推理游戏。游戏的内容是这样的,明明的同学们先商量好由其中的一个人充当罪犯(在明明不知情的情况下),明明的任务就是找出这个罪犯。接着,明明逐个询问每一个同学,被询问者可能会说:
证词中出现的其他话,都不列入逻辑推理的内容。 明明所知道的是,他的同学中有N个人始终说假话,其余的人始终说真。 现在,明明需要你帮助他从他同学的话中推断出谁是真正的凶手,请记住,凶手只有一个! 输入格式
输入由若干行组成,第一行有三个整数,M(1≤M≤20)、N(1≤N≤M)和P(1≤P≤100);M是参加游戏的明明的同学数,N是其中始终说谎的人数,P是证言的总数。 接下来M行,每行是明明的一个同学的名字(英文字母组成,没有空格,全部大写)。 往后有P行,每行开始是某个同学的名宇,紧跟着一个冒号和一个空格,后面是一句证词,符合前表中所列格式。证词每行不会超过250个字符。 输入中不会出现连续的两个空格,而且每行开头和结尾也没有空格。 输出格式
如果你的程序能确定谁是罪犯,则输出他的名字;如果程序判断出不止一个人可能是罪犯,则输出 "Cannot Determine";如果程序判断出没有人可能成为罪犯,则输出 "Impossible"。 输入输出样例
输入 #1复制
3 1 5
MIKE
CHARLES
KATE
MIKE: I am guilty.
MIKE: Today is Sunday.
CHARLES: MIKE is guilty.
KATE: I am guilty.
KATE: How are you??
输出 #1复制
MIKE
哎呀呀,这个题看起来好难的样子,让计算器斯烤,他怕不是把我当成了神?
(神明的声音响起)“人类啊,你直接遍历日期和罪犯,如果合理就完事了对吧,有多个罪犯的情况就去处理啊,只需要O(7M(P+2M))的效率(应该)就可以了。真是愚蠢的人类……”
哎呀神明显灵了!但貌似神明说的明显不够缜密啊。我再来补充一下吧。
如果有一个人说真话了又说假话了,他是说真话的还是说假话的呢?
比如我们设定今天周1,他自己是凶手。但他说今天周2,他自己是凶手,他是说真话的还是说假话的?
虽然这种情况存在,但有这种情况的时候肯定假设错误了。不知道为啥的同学肯定没好好看题……
明明所知道的是,他的同学中有N个人始终说假话,其余的人始终说真。
所以说,如果有个人在这次的设定中既说真话又说假话,那我们就可以换一个假设了(与题目描述不符)。
继续继续
会不会有一些狡诈的同学只说废话?
答案是会的(我下载数据看了)
对于这种人怎么办呢?他可能是说假话的人设,也可能是说真话的。
有个大侦探说过:“排除所有不可能,剩下的再不可思议,也是可能。”但这个情况并不是不可能……
我们把他看成可能,如果能确定凶手都是可能,也就是说,如果我们确定说假话的人数在n以下,而且说谎人数+不确定人数>n。这个情况就是合理的。
我们就可以把凶手标记一下。如果下次遇到不同的凶手,就可以说没有解了。
当然我之前想过会不会有同学叫“罪犯”,他说我是罪犯是说我叫“罪犯”,而不是我是犯罪者的意思?
或者叫周一周二周三……
真的有
但题目很友善(不友善没法做了),姓名全是大写,说话内容全是小写(good)。
所以大家不要胡思乱想了。
接下来就是讲解模拟的时候了:
本人把他的证词分为了1,2,3三种类型。
类型1是说周几的,用rq(日期)表记
类型2是说罪犯是谁,用zfbh(罪犯编号)表记
类型3是说谁不是罪犯,用zfbh(罪犯编号)标记
(没错他俩一样,我懒得定义新变量了,反正都是和罪犯有关)
然后开始写判断,判断周几简单粗暴
(嘻嘻打表真香)
判断类型2和3也是打表啦(快乐)
然后就是一些和谐的模拟,就是判断和你设定的相符不相符,然后做一些简单处理,我写在注释里吧。
好啦好啦,看看我写的很长很长的代码吧:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<map>
using namespace std;
struct hehe
{
long long lx,bh,rq,zfbh;//这个是证言情况的数组,lx是类型,zfbh是罪犯编号,rq是日期,bh是证人编号。
}sz[205];
string pdrq[10]={" ","Today is Monday.","Today is Tuesday.","Today is Wednesday.","Today is Thursday.","Today is Friday.","Today is Saturday.","Today is Sunday."};//打表判断周几
long long n,m,p,bqc,sjhd,xs,bcl;//bqc是不清楚的意思,表示有多少人一直说胡话。sjhd是说假话的,这个名字很清楚吧。
string name,zname,s[100];
string zy;
map<string,int>ys;
map<string,int>mp;
int main()
{
cin>>m>>n>>p;
for(int i=1;i<=m;i++)
{
cin>>s[i];//读入名字
mp[s[i]]=i;//本名字的编号为i
}
for(int i=1;i<=p;i++)
{
cin>>name;//输入名字,他输入证言是“名字+:+空格+证言+回车 ”我为什么打回车先按下不表,等等再说。
zname="";
for(int j=0;j<name.length()-1;j++)
{
zname+=name[j];//zname才是name,name是名字+:
}
sz[i].bh=mp[zname];
getline(cin,zy);//带空格我选getline。
zy.erase(zy.end()-1);//截取,就是删掉后面的回车(评测姬和我的情况不一样导致的)
for(int j=1;j<=7;j++)
{
if(zy==" "+pdrq[j])//他在说日期哎
{
sz[i].lx=1;//lx为1
sz[i].rq=j;//日期为j
}
}
int bj=0;
if(zy==" I am guilty.")//他在说罪犯哎
{
sz[i].zfbh=mp[zname];
sz[i].lx=2;
}else if(zy==" I am not guilty.")//他在说清白的人哎
{
sz[i].zfbh=mp[zname];
sz[i].lx=3;
}else
{
for(int j=1;j<=m;j++)
{
if(zy==" "+s[j]+" is guilty.")//他在说罪犯哎
{
sz[i].zfbh=j;
sz[i].lx=2;
}else if(zy==" "+s[j]+" is not guilty.")//他在说清白的人哎
{
sz[i].zfbh=j;
sz[i].lx=3;
}
}
}
}
for(int i=1;i<=m;i++)
{
for(int j=1;j<=7;j++)//暴力枚举罪犯编号和日期
{
bcl=0;
for(int u=1;u<=m;u++)//初始化
{
ys[s[u]]=0;
}
for(int u=1;u<=p;u++)
{
if(sz[u].lx==1)//判断证言类型
{
if(sz[u].rq==j)
{
if(ys[s[sz[u].bh]]==0)
{
ys[s[sz[u].bh]]=1;
}else if(ys[s[sz[u].bh]]!=1)//前后不符,就是也说真话也说假话(后面的差不多一样,不写了)
{
bcl=1;
}
}else
{
if(ys[s[sz[u].bh]]==0)
{
ys[s[sz[u].bh]]=-1;
}else if(ys[s[sz[u].bh]]!=-1)
{
bcl=1;
}
}
}else if(sz[u].lx==2)
{
if(sz[u].zfbh==i)
{
if(ys[s[sz[u].bh]]==0)
{
ys[s[sz[u].bh]]=1;
}else if(ys[s[sz[u].bh]]!=1)
{
bcl=1;
}
}else
{
if(ys[s[sz[u].bh]]==0)
{
ys[s[sz[u].bh]]=-1;
}else if(ys[s[sz[u].bh]]!=-1)
{
bcl=1;
}
}
}else if(sz[u].lx==3)
{
if(sz[u].zfbh!=i)
{
if(ys[s[sz[u].bh]]==0)
{
ys[s[sz[u].bh]]=1;
}else if(ys[s[sz[u].bh]]!=1)
{
bcl=1;
}
}else
{
if(ys[s[sz[u].bh]]==0)
{
ys[s[sz[u].bh]]=-1;
}else if(ys[s[sz[u].bh]]!=-1)
{
bcl=1;
}
}
}
}
if(bcl==1)//这个设定是不合理的。
{
continue;
}
bqc=0;
sjhd=0;
for(int u=1;u<=m;u++)//判断说谎的人和不确定的人。
{
if(ys[s[u]]==0)
{
bqc++;
}
if(ys[s[u]]==-1)
{
sjhd++;
}
}
if(sjhd<=n&&bqc+sjhd>=n)//合理
{
if(xs!=i&&xs!=0)//之前有过不一样的凶手,也就是说凶手可能有多个,不符合题目描述,退出。
{
cout<<"Cannot Determine"<<endl;
exit(0);
}
xs=i;//这是唯一的凶手
}
}
}
if(xs==0)//根本没有凶手
{
cout<<"Impossible"<<endl;
exit(0);
}
cout<<s[xs];//输出
return 0;
}
这个题真是恶心啊,就说到这里吧(是的结束了)。
P1039 侦探推理(洛谷)的更多相关文章
- Luogu P1039 侦探推理(模拟+枚举)
P1039 侦探推理 题意 题目描述 明明同学最近迷上了侦探漫画<柯南>并沉醉于推理游戏之中,于是他召集了一群同学玩推理游戏.游戏的内容是这样的,明明的同学们先商量好由其中的一个人充当罪犯 ...
- 洛谷P1039 侦探推理(模拟)
侦探推理 题目描述 明明同学最近迷上了侦探漫画<柯南>并沉醉于推理游戏之中,于是他召集了一群同学玩推理游戏.游戏的内容是这样的,明明的同学们先商量好由其中的一个人充当罪犯(在明明不知情的情 ...
- 洛谷 P1039侦探推理
/* 枚举罪犯和星期几,那么所有人说的话是真是假一目了然. 首先一个人不能既说真话又说假话. 即: I am guilty. I am not guilty. 因为非真即假,所以直接判断impossi ...
- [NOIP2003] 提高组 洛谷P1039 侦探推理
题目描述 明明同学最近迷上了侦探漫画<柯南>并沉醉于推理游戏之中,于是他召集了一群同学玩推理游戏.游戏的内容是这样的,明明的同学们先商量好由其中的一个人充当罪犯(在明明不知情的情况下),明 ...
- 洛谷 P1039 侦探推理
题目:https://www.luogu.org/problemnew/show/P1039 分析: 这道题是一道有技术含量的模拟,我们主要是不要让计算机向人一样思考,只需要让他穷举变化的星期几和当罪 ...
- 洛谷P1039侦探推理题解
#include<cstdio> #include<cstring> #include<string> #include<iostream> using ...
- P1039 侦探推理
题目描述 明明同学最近迷上了侦探漫画<柯南>并沉醉于推理游戏之中,于是他召集了一群同学玩推理游戏.游戏的内容是这样的,明明的同学们先商量好由其中的一个人充当罪犯(在明明不知情的情况下),明 ...
- LUOGU P1039 侦探推理 (字符串+模拟)
传送门 解题思路 一道%你神题,\(string\)好强大啊..首先枚举一个周几,再枚举一个罪犯是谁,然后判断的时候就是枚举所有人说的话.定义\(fAKe[i]\)表示第\(i\)个人说的是真话还是假 ...
- 【洛谷P1039】侦探推理
侦探推理 题目链接 这是一道恶心至极的模拟题 我们可以枚举罪犯是谁,今天是星期几,从而判断每个人说的话是真是假 若每个人说的话的真假一致,且说谎话的人数<=k且说真话的人数<=m-k,就是 ...
随机推荐
- Typescript的interface、class和abstract class
interface,class,和abstract class这3个概念,既有联系,又有区别,本文尝试着结合官方文档来阐述这三者之间的关系. 1. Declaration Merging Declar ...
- Windows7/10实现ICMP(ping命令)
如果觉得本文如果帮到你或者你想转载都可以,只需要标注出处即可.谢谢 利用ICMP数据包.C语言实现Ping命令程序,能实现基本的Ping操作,发送ICMP回显请求报文,用于测试—个主机到只一个主机之间 ...
- 高性能IO —— Reactor(反应器)模式
讲到高性能IO绕不开Reactor模式,它是大多数IO相关组件如Netty.Redis在使用的IO模式, 为什么需要这种模式,它是如何设计来解决高性能并发的呢? 最最原始的网络编程思路就是服务器用一个 ...
- 重学 Java 设计模式:实战中介者模式「按照Mybaits原理手写ORM框架,给JDBC方式操作数据库增加中介者场景」
作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 同龄人的差距是从什么时候拉开的 同样的幼儿园.同样的小学.一样 ...
- git和github入门指南(2.1)
2.git常用命令 2.1.git的三个区 1.工作区 工作区就是你项目所在目录,这个目录是可以非常直观的看到的,编写代码主要在这个目录进行,例如: 2.暂存区 暂存区从字面上去理解就是用来暂时保存项 ...
- Redis系列(六):数据结构QuickList(快速列表)源码解析
1.介绍 Redis在3.2版本之前List的底层编码是ZipList和LinkedList实现的 在3.2版本之后,重新引入了QuickList的数据结构,列表的底层都是QuickList实现 当L ...
- 在Ubuntu 16.04上编译OpenJDK8的源代码
本文将详细介绍在Ubuntu16.04上对OpenJDK8进行编译. 1.准备编译环境 使用的操作系统为Ubuntu16.04,如果读者没有安装Ubuntu,可以在Windows上使用虚拟机的方式进行 ...
- Windows7 PowerShell 2.0升级到 PowerShell 5.1
Windows7 sp1内置的PowerShell的版本是v2.0,现需要将其升级到v5.1,过程中有一个环节需要引起注意,为了以后查阅的方便,现将其记录下来. 1 查看PowerShell版本 Wi ...
- Springboot 2.X的RequestMapping 的映射路径怎么看不到了?
在使用spring boot 1.X的时候我们可以在console中看到mapping的映射路径 2020-01-12 19:10:19.996 INFO 2711 --- [ main] s.w.s ...
- PHPstorm常用快捷键(Windows)
本文整理本人在日常工作中使用最频繁的PHPstorm快捷键,以作为自己的总结备忘,也希望能够帮到有需要的小伙伴. 以下快捷键大致按本人的使用频率从高到低来介绍. 1.复制.粘贴 Ctrl+c .Ctr ...