P1039 [NOIP2003 提高组] 侦探推理

这篇具有很好参考价值的文章主要介绍了P1039 [NOIP2003 提高组] 侦探推理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

题目描述

明明同学最近迷上了侦探漫画《柯南》并沉醉于推理游戏之中,于是他召集了一群同学玩推理游戏。游戏的内容是这样的,明明的同学们先商量好由其中的一个人充当罪犯(在明明不知情的情况下),明明的任务就是找出这个罪犯。接着,明明逐个询问每一个同学,被询问者可能会说:

P1039 [NOIP2003 提高组] 侦探推理

证词中出现的其他话,都不列入逻辑推理的内容。

明明所知道的是,他的同学中有 �N 个人始终说假话,其余的人始终说真。

现在,明明需要你帮助他从他同学的话中推断出谁是真正的凶手,请记住,凶手只有一个!

输入格式

输入由若干行组成。

第一行有三个整数,�,�M,N 和 �P。�M 是参加游戏的明明的同学数,�N 是其中始终说谎的人数,�P 是证言的总数。

接下来 �M 行,每行是明明的一个同学的名字(英文字母组成,没有空格,全部大写)。

往后有 �P 行,每行开始是某个同学的名宇,紧跟着一个冒号和一个空格,后面是一句证词,符合前表中所列格式。证词每行不会超过 250250 个字符。

输入中不会出现连续的两个空格,而且每行开头和结尾也没有空格。

输出格式

如果你的程序能确定谁是罪犯,则输出他的名字;如果程序判断出不止一个人可能是罪犯,则输出 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

说明/提示

对于 100%100% 数据,满足 1≤�≤201≤M≤20,0≤�≤�0≤N≤M,1≤�≤1001≤P≤100。

【题目来源】

NOIP 2003 提高组第二题

//记录每一句话是谁说的以及这句话的内容
//可以用map存人名对应的下标 

//我们枚举每一个人i,假设i是罪犯
//然后枚举今天是星期几,用day表示 
//然后判断有没有矛盾

//如何判断?
//进行每一次判断的时候,先使所有人的状态不确定,也就是不知道他们会说真话假话
//TF[a]==-1是不确定,TF[a]=1是说真话,TF[a]=0是说假话
//T是说真话的人数,F是说假话的人数 
//设罪犯为 i 
//设flag为这句话是真话还是假话,flag=1是真话,flag=0是假话 
//id是说这句话的人 
//枚举每一句话
//    看一下id以前的状态,如果状态不确定(TF==-1),就TF[id]=flag
//    否则,如果和以前状态一样(TF[id]==flag),就没有矛盾,
//    TF[id]!=flag就是出现了矛盾(因为一个人始终直说一种话),判断不出来了,直接return去枚举下一个人是罪犯 
//如果F>n或者T>m-n了,也就是说假话的人数超过了题目中给的人数,矛盾,return
//如果找到了不止一个罪犯,输出"Cannot Determine",直接exit(0) 

//怎么知道这句话是真话假话? 
//①如果话里有 "I am guilty."
//    那么看一下id是不是i,不是的话,就是在说假话
//②话里有"I am not guilty"
//    看一下id是不是i,不是的话,就是在说真话,否则就是假话 
//③话里有"xxx is guilty"
//    如果xxx是i的话,就是真话,否则是假话
//④话里有"xxx is not guilty"
//    如果xxx不是i的话,就是真话,否则是假话
//⑤话里有"Today is XXX"
//    如果xxx与day一样,就是真话,否则是假话文章来源地址https://www.toymoban.com/news/detail-425759.html

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
using namespace std;

string S[10]=
{
	"Today is Sunday.",
	"Today is Monday.",
	"Today is Tuesday.",
	"Today is Wednesday.",
	"Today is Thursday.",
	"Today is Friday.",
	"Today is Saturday.",
};

int m,n,p;
int T,F,ans;
int TF[25];
struct Sen
{
	int id;
	string s;
}sen[105];
map<string,int> ma;

bool judgeTF(int id,bool flag)	//看一下有没有冲突,return 1 表示有冲突 
{
	if(TF[id]==-1)		//状态不确定 
	{
		TF[id]=flag;	//赋状态 
		if(flag)	//说真话的人数++ 
			++T;
		else	//说假话的人数++ 
			++F;
	}
	else
		return TF[id]!=flag;	//和之前的一不一样,一样返回0,不一样返回1 
	if(F>n||T>m-n)	//说假话的人比n多或者是说真话的人比m-n多 
		return 1;
	return 0;
}

void judge(int id,string day)
{
	memset(TF,-1,sizeof(TF));	//所有人都不知道说的是真话假话 
	T=F=0;		//说真话、假话人数置0 
	string tmp;
	for(int i=1;i<=p;++i)
	{
		int pos=sen[i].s.find("I am guilty.");	//pos为-1则没说这句话 
		if(~pos)
		{
			if(judgeTF(sen[i].id,sen[i].id==id))	//因为我们假设了id是罪犯,所以不是id的人就不是罪犯,就是在说假话
				return;
		}
		pos=sen[i].s.find("I am not guilty");
		if(~pos)
		{
			if(judgeTF(sen[i].id,sen[i].id!=id))
				return;
		}
		pos=sen[i].s.find(" is guilty.");
		if(~pos)
		{
			tmp=sen[i].s;
			tmp.erase(pos,11);
			if(judgeTF(sen[i].id,ma[tmp]==id))
				return;
		}
		pos=sen[i].s.find(" is not guilty.");
		if(~pos)
		{
			tmp=sen[i].s;
			tmp.erase(pos,15);
			if(judgeTF(sen[i].id,ma[tmp]!=id))
				return;
		}
		pos=sen[i].s.find("Today is ");
		if(~pos)
		{
			if(judgeTF(sen[i].id,sen[i].s==day))
				return;
		}
	}
	if(ans&&ans!=id)	//找到了不止一个罪犯 
	{
		puts("Cannot Determine");	//不能确定 
		exit(0);
	}
	ans=id;		//id是罪犯 
}

string s[25],name,a;
int main()
{
	scanf("%d%d%d",&m,&n,&p);
	for(int i=1;i<=m;++i)
	{
		cin>>s[i];
		ma[s[i]]=i;		//存名字标号 
	}
	for(int i=1;i<=p;++i)
	{
		cin>>name;		//输入说话者 
		name.erase(name.length()-1,1);		//把后边的冒号搞掉 
		getline(cin,a);
		a.erase(0,1);	//把前边的空格搞掉 
		if(a[a.length()-1]=='\n'||a[a.length()-1]=='\r')	//把坑爹的换行符搞掉 
			a.erase(a.length()-1,1);
		sen[i].id=ma[name];		//存说话者 
		sen[i].s=a;		//存说话内容 
	}
	for(int i=1;i<=m;++i)	//假设第i个人是罪犯 
		for(int j=0;j<7;++j)	//假设今天是S[j]天 
			judge(i,S[j]);
	if(!ans)	//找不到罪犯 
		puts("Impossible");
	else
		cout<<s[ans];	//罪犯名字 
	return 0;
}

到了这里,关于P1039 [NOIP2003 提高组] 侦探推理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • NOIP2003普及组复赛T2:数字游戏

    题目链接:NOIP2003普及组复赛T2 - 数字游戏 丁丁最近沉迷于一个数字游戏之中。这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易。游戏是这样的,在你面前有一圈整数(一共 n n n 个),你要按顺序将其分为 m m m 个部分

    2024年02月09日
    浏览(28)
  • P1012 [NOIP1998 提高组] 拼数

    设有 �n 个正整数 �1…��a1​…an​,将它们联接成一排,相邻数字首尾相接,组成一个最大的整数。 第一行有一个整数,表示数字个数 �n。 第二行有 �n 个整数,表示给出的 �n 个整数 ��ai​。 一个正整数,表示最大的整数 输入 #1 复制 输出 #1 复制 输入 #

    2023年04月08日
    浏览(23)
  • P1013 [NOIP1998 提高组] 进制位

    著名科学家卢斯为了检查学生对进位制的理解,他给出了如下的一张加法表,表中的字母代表数字。 例如: 其含义为: �+�=�L+L=L,�+�=�L+K=K,�+�=�L+V=V,�+�=�L+E=E �+�=�K+L=K,�+�=�K+K=V,�+�=�K+V=E,�+�=��K+E=KL ⋯⋯ �+�=��E+E=KV 根据这些规则可推

    2023年04月08日
    浏览(24)
  • P1967 [NOIP2013 提高组] 货车运输 题解

    原题地址 由于题目要求的是使两点之间的最小边权最大,所以可以构造最大生成树(最大生成树一定是最大瓶颈生成树,而瓶颈生成树上两点之间的路径,在原图中的所有路径中,最小边权仍然最大,即满足题目要求,详见 https://oi-wiki.org/graph/mst/#瓶颈生成树 ),答案为最大

    2024年04月08日
    浏览(27)
  • P1125 [NOIP2008 提高组] 笨小猴——C++

    笨小猴的词汇量很小,所以每次做英语选择题的时候都很头疼。但是他找到了一种方法,经试验证明,用这种方法去选择选项的时候选对的几率非常大! 这种方法的具体描述如下:假设 maxn text{maxn} maxn 是单词中出现次数最多的字母的出现次数, minn text{minn} minn 是单词中出

    2024年02月02日
    浏览(28)
  • [NOIP2001 提高组] 一元三次方程求解(洛谷)

    有形如: a x 3 + b x 2 + c x + d = 0 a x^3 + b x^2 + c x + d = 0 a x 3 + b x 2 + c x + d = 0 这样的一个一元三次方程。给出该方程中各项的系数( a , b , c , d a,b,c,d a , b , c , d 均为实数),并约定该方程存在三个不同实根(根的范围在 − 100 -100 − 100 至 100 100 100 之间),且根与根之差的绝对值

    2024年01月22日
    浏览(32)
  • 【Java贪心】P5019 [NOIP2018 提高组] 铺设道路

    NOIP2018 提高组 D1T1 春春是一名道路工程师,负责铺设一条长度为 n n n 的道路。 铺设道路的主要工作是填平下陷的地表。整段道路可以看作是 n n n 块首尾相连的区域,一开始,第 i i i 块区域下陷的深度为 d i d_i d i ​ 。 春春每天可以选择一段连续区间 [ L , R ] [L,R] [ L , R ] ,填

    2023年04月11日
    浏览(23)
  • #P1007. [NOIP2007提高组] 矩阵取数游戏

    帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的 n times mn×m 的矩阵,矩阵中的每个元素 a_{i,j}ai,j​ 均为非负整数。游戏规则如下: 每次取数时须从每行各取走一个元素,共 nn 个。经过 mm 次后取完矩阵内所有元素; 每次取走的各个元素只能是该元素所在行的行

    2024年02月15日
    浏览(34)
  • 【洛谷 P1097】[NOIP2007 提高组] 统计数字 题解(映射)

    注意 :数据可能存在加强。 某次科研调查时得到了 n n n 个自然数,每个数均不超过 1.5 × 1 0 9 1.5 times 10^9 1.5 × 1 0 9 。已知不相同的数不超过 1 0 4 10^4 1 0 4 个,现在需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序输出统计结果。 共 n + 1 n+1 n + 1 行。 第一

    2024年02月09日
    浏览(37)
  • 【洛谷 P1003】[NOIP2011 提高组] 铺地毯 题解(数组+贪心算法)

    为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯。一共有 n n n 张地毯,编号从 1 1 1 到 n n n 。现在将这些地毯按照编号从小到大的顺序平行于坐标轴先后铺设,后铺的地毯覆盖在前面已经铺好的地毯之上

    2023年04月24日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包