侦探推理

2 篇文章 0 订阅

1205: 侦探推理

时间限制: 1 Sec  内存限制: 128 MB

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

证词中出现的其他话,都不列入逻辑推理的内容。
明明所知道的是,他的同学中有N个人始终说假话,其余的人始终说真。
现在,明明需要你帮助他从他同学的话中推断出谁是真正的凶手,请记住,凶手只有一个!

 

输入
输入由若干行组成,第一行有二个整数,M(1≤M≤20)、N(1≤N≤M)和P(1≤P≤100);
M是参加游戏的明明的同学数,N是其中始终说谎的人数,P是证言的总数。接下来M行,
每行是明明的一个同学的名字(英文字母组成,没有主格,全部大写)。
往后有P行,每行开始是某个同学的名宇,紧跟着一个冒号和一个空格,后面是一句证词,符合前表中所列格式。证词每行不会超过250个字符。
输入中不会出现连续的两个空格,而且每行开头和结尾也没有空格。

 

输出
如果你的程序能确定谁是罪犯,则输出他的名字;如果程序判断出不止一个人可能是罪犯,则输出 Cannot Determine;如果程序判断出没有人可能成为罪犯,则输出 Impossible。

 

样例输入
2 2 4
HELLO
GUILTY
HELLO: What is your name?
GUILTY: I am GUILTY.
GUILTY: Are you guilty?
HELLO: I am not guilty.

 

样例输出
HELLO

 

来源
noip 2003 提高

FZOJ1205

 

题解

这道题是枚举题,其难点主要是陷阱超多。
首先将话语读入,选出有用的话,并保存成关系。
题目中主要判断真话和假话的依据是某人是否是罪犯和今天是星期几,枚举所有的情况,并判断在该情况下是否有冲突。冲突主要有:
1.某个人说的话中既有真话,又有假话。
2.确定说假话的人数大于说假话的人数。

3.总人数减去确定说真话的人数后小于说假话的人数。

如果没有以上任何冲突,说明在该情况下是符合题意的,则该情况下的罪犯是正确的。

所有情况枚举完后,如果有1个人确定是犯罪,输出该人的人名;如果没有人确定是犯罪,输出Impossible;如果有超过1个人确定是犯罪,输出Cannot Determine。

程序不是很难写,但如果考虑到所有可能的陷阱就很困难了。

当你看到数据后,你可能觉得这道题目太有趣了。

1.样例输入,陷阱数据,有个人叫犯罪,其实他不是犯罪,如果在输入时把话语全部转换成大写或小写,就错了。

2.常规数据,有个人既说自己是罪犯,又说自己不是罪犯。

3. 常规数据,只要程序基本正确就可以得分。

4.常规数据,这七个人的父母真是奇葩,名字都是星期,注意不要把名字和话语混淆。

5.常规数据。

6.常规数据,输入就像一幅画一样。

7.陷阱数据,第一段话guity(有罪的)是错误的,第二段话是双重否定句,根据题意都应该排除掉。要求程序必须完全比对话语是否一样。另外注意即使没有任何线索,但因为只有1个人,所以还是可以确定这个人是罪犯。

8.陷阱数据,同样,所有话都要被排除。“Am I???”是什么意思?

9.陷阱数据,“I”是人名,要根据谓语判断是它表示的意识是人名还是“我”。

10.陷阱数据,一个人名有204个字符长,虽然输入的话毫无意义,但如果字符数组开的不够大,会运行错误。

人名是汉语拼音,翻译成汉语,竟然是一段话:曾经有一段真挚的感情。芳,在我面前,我没有珍惜。等到失去了以后,才追悔莫及。人世间最痛苦的事莫过于此。如果上天能给我一个再来一次的机会,我会对那个女孩子说三个字……(后面他说了三句毫无意义的话:“I love you!”、“If there must be a deadline,”、“I hope it is 10000 years!!!”)。

其实还有个陷阱数据没有涉及到,就是有用的话必须以句号结束,否则应该排除。

如果这道题输出Impossible或Cannot都可以骗到10分。

总而言之,这道题是说明“非明文禁止者,皆无不可能”的好题。

 

#include<cstdio>
#include <string.h>
int main()
{
	int a,b,c,d,e,f,g,i,m,n,j,x[110][5]={0},z[30]={0},u[30]={0},y;
	char w[30][300]={0},v[100]={0};
	scanf("%d %d %d",&a,&b,&c);
	for(i=1;i<=a;i++)
	{
		scanf(" %s",&w[i]);
	}
	n=1;
	for(i=1;i<=c;i++)
	{
		scanf(" %s",v);
		d=strlen(v);
		v[d-1]='\0';
		d=-1;
		for(m=1;m<=a;m++)
		{
			e=strcmp(v,w[m]);
			if(e==0) d=m;
		}
		if(d==-1)
		{
			y=1;
			while(y==1)
			{
				d=strlen(v);
				if((v[d-1]=='.')||(v[d-1]=='!')||(v[d-1]=='?')||(v[d-1]==',')) y=2;
				else scanf(" %s",v);
			}
			scanf(" %s",v);
			d=strlen(v);
			v[d-1]='\0';
			d=-1;
			for(m=1;m<=a;m++)
			{
				e=strcmp(v,w[m]);
				if(e==0) d=m;
			}
		}
		scanf(" %s",v);
		if((v[0]=='T')&&(v[1]=='o')&&(v[5]=='\0'))
		{
			scanf(" %s",v);
			scanf(" %s",v);
			if((v[0]=='M')&&(v[1]=='o')) f=1;
			if((v[0]=='T')&&(v[1]=='u')) f=2;
			if((v[0]=='W')&&(v[1]=='e')) f=3;
			if((v[0]=='T')&&(v[1]=='h')) f=4;
			if((v[0]=='F')&&(v[1]=='r')) f=5;
			if((v[0]=='S')&&(v[1]=='a')) f=6;
			if((v[0]=='S')&&(v[1]=='u')) f=7;
			x[n][0]=d;
			x[n][1]=0;
			x[n][2]=f;
			n=n+1;
			continue;
		}
		f=-1;
		for(m=1;m<=a;m++)
		{
			e=strcmp(v,w[m]);
			if(e==0) f=m;
		}
		if(f!=-1)
		{
			scanf(" %s",v);
			scanf(" %s",v);
			if((v[0]=='g')&&(v[1]=='u'))
			{
				x[n][0]=d;
				x[n][1]=f;
				x[n][2]=1;
				n=n+1;
				continue;
			}
			if((v[0]=='n')&&(v[1]=='o'))
			{
				scanf(" %s",v);
				if((v[0]=='g')&&(v[1]=='u'))
				{
					x[n][0]=d;
					x[n][1]=f;
					x[n][2]=2;
					n=n+1;
					continue;
				}
			}
		}
		if((v[0]=='I')&&(v[1]=='\0'))
		{
			scanf(" %s",v);
			scanf(" %s",v);
			if((v[0]=='g')&&(v[1]=='u'))
			{
				x[n][0]=d;
				x[n][1]=d;
				x[n][2]=1;
				n=n+1;
				continue;
			}
			if((v[0]=='n')&&(v[1]=='o'))
			{
				scanf(" %s",v);
				if((v[0]=='g')&&(v[1]=='u'))
				{
					x[n][0]=d;
					x[n][1]=d;
					x[n][2]=2;
					n=n+1;
					continue;
				}
			}
		}
		y=1;
		while(y==1)
		{
			d=strlen(v);
			if((v[d-1]=='.')||(v[d-1]=='!')||(v[d-1]=='?')||(v[d-1]==',')) y=2;
			else scanf(" %s",v);
		}
	}
	for(i=1;i<=a;i++)
	{
		for(m=1;m<=7;m++)
		{
			d=0;
			for(j=1;j<n;j++)
			{
				if(x[j][1]==0)
				{
					if(x[j][2]!=m)
					{
						u[x[j][0]]=1;
					}
				}
				else
				{
					e=x[j][0];
					if((x[j][2]==1)&&(x[j][1]!=i)&&(u[x[j][0]]!=2)) u[e]=1;
					if((x[j][2]==1)&&(x[j][1]!=i)&&(u[x[j][0]]==2)) d=1;
					if((x[j][2]==1)&&(x[j][1]==i)&&(u[x[j][0]]!=1)) u[e]=2;
					if((x[j][2]==1)&&(x[j][1]==i)&&(u[x[j][0]]==1)) d=1;
					if((x[j][2]==2)&&(x[j][1]==i)&&(u[x[j][0]]!=2)) u[e]=1;
					if((x[j][2]==2)&&(x[j][1]==i)&&(u[x[j][0]]==2)) d=1;
					if((x[j][2]==2)&&(x[j][1]!=i)&&(u[x[j][0]]!=1)) u[e]=2;
					if((x[j][2]==2)&&(x[j][1]!=i)&&(u[x[j][0]]==1)) d=1;
				}
			}
			e=0;
			g=0;
			for(j=1;j<=a;j++)
			{
				if(u[j]==1) e=e+1;
				if(u[j]==2) g=g+1;
				u[j]=0;
			}
			if((d==0)&&(e<=b)&&(g<=a-b)) z[i]=1;
		}
	}
	g=0;
	f=0;
	for(i=1;i<=a;i++)
	{
		if(z[i]==1)
		{
			g=g+1;
			f=i;
		}
	}
	if(g==0)
	{
		printf("Impossible");
	}
	if(g==1)
	{
		printf("%s",w[f]);
	}
	if(g==2)
	{
		printf("Cannot Determine");
	}
    return 0;
}
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值