【NOIP2003】侦探原理 大模拟 附数据 附题解 附注意

题解:处理证词(我是处理得每个人指证谁,保谁,说今天周几),枚举检查(我是先外层枚举周几,然后枚举每个人说了什么检查)。

注意:

检查:

1.记录已确定说谎人数,不说谎人数。

2. 怎么方便怎么来,不要想着会超时。永远0ms!

3. 函数返回值的时机。

处理数据!!:

1. 全说谎,全不说谎

2. 名字叫“GUILTY”、“I”、星期几、特别长

3. 证词一旦不与表中相同,就作废!(正确的证词后面加一点点点废话,你懂的)

4. 测点怎么没有人叫TODAY?…………

5 .数据一定要读完。

其他:

什么输出时多一个少一个空格神马的一定要注意。


附代码,代码后面附NOIP数据,

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 30
#define M 300
using namespace std;


char names[N][M];
char t[N][M];

int n,m,m2,p;
int hate[N][N],love[N][N],day[N][N];
int numa[N],numb[N],numc[N];

void deal()
{
	int i,j,k;
	int a,b;
	scanf("%d%d%d",&n,&m,&p);m2=n-m;
	for(i=1;i<=n;i++)scanf("%s",names[i]+1);
	for(i=1;i<=p;i++)
	{
		scanf("%s",t[1]+1);
		for(k=1;k<=n;k++)/*判断指证者(a)*/
		{
			for(j=1;t[1][j]!=':';j++)if(t[1][j]!=names[k][j])break;
			if(t[1][j]==':')
			{
				a=k;
				break;
			}
		}
		scanf("%s",t[2]+1);
		if(strcmp(t[2]+1,"Today")==0)/*证词说的是日期*/
		{
			scanf("%s",t[3]);
			scanf("%s",t[3]);
			if(strcmp(t[3],"Monday.")==0)day[a][++numc[a]]=1;
			if(strcmp(t[3],"Tuesday.")==0)day[a][++numc[a]]=2;
			if(strcmp(t[3],"Wednesday.")==0)day[a][++numc[a]]=3;
			if(strcmp(t[3],"Thursday.")==0)day[a][++numc[a]]=4;
			if(strcmp(t[3],"Friday.")==0)day[a][++numc[a]]=5;
			if(strcmp(t[3],"Saturday.")==0)day[a][++numc[a]]=6;
			if(strcmp(t[3],"Sunday.")==0)day[a][++numc[a]]=7;
		}
		else
		{
			if(strcmp(t[2]+1,"I")==0)b=a;
			else for(b=0,k=1;k<=n;k++)
			{
				for(j=1;t[2][j]!='\0';j++)if(t[2][j]!=names[k][j])break;
				if(t[2][j]=='\0')
				{
					b=k;
					break;
				}
			}
			if(!b)/*证词作废*/
			{
				gets(t[3]);
				continue;
			}
			else /*已经判断出被指证者*/
			{
				scanf("%s",t[3]);
				if(strcmp(t[3],"is")==0&&t[2][1]=='I')b=9;
				scanf("%s",t[3]);
				if(strcmp(t[3],"not")==0)
				{
					love[a][++numb[a]]=b;
					gets(t[4]);
					if(strcmp(t[4]+1,"guilty."))numb[a]--;
				}
				else
				{
			 		hate[a][++numa[a]]=b;
			 		if(strcmp(t[3],"guilty."))numa[a]--;
				}
			}
		}
	}
}
bool handle(int x)
{
	int A,B;/*已确定说真话假话的人数*/
	int i,j,dy,bel,brek;
	for(dy=1;dy<=7;dy++)
	{
		A=B=brek=0;
		for(i=1;i<=n;i++)
		{
			bel=0;
			for(j=1;j<=numc[i];j++)
			{
				if(day[i][j]==dy)
				{
					if(bel==-1)
					{
						brek=1;
						break;
					}
					bel=1;
				}
				else
				{
					if(bel==1)
					{
						brek=1;
						break;
					}
					bel=-1;
				}
			}

			if(brek)break;

			for(j=1;j<=numa[i];j++)
			{
				if(hate[i][j]==x)
				{
					if(bel==-1)
					{
						brek=1;
						break;
					}
					bel=1;
				}
				else
				{
					if(bel==1)
					{
						brek=1;
						break;
					}
					bel=-1;
				}
			}

			if(brek)break;
			
			for(j=1;j<=numb[i];j++)
			{
				if(love[i][j]==x)
				{
					if(bel==1)
					{
						brek=1;
						break;
					}
					bel=-1;
				}
				else
				{
					if(bel==-1)
					{
						brek=1;
						break;
					}
					bel=1;
				}
			}

			if(bel==1)A++;
			if(bel==-1)B++;
			if(B>m||A>m2)brek=1;
			if(brek)break;
			
		}
		if(!brek)return 1;
	}
	return 0;
}
int main()
{
//	freopen("logic.in","r",stdin);
//	freopen("logic.ou","w",stdout);
	int i,flag=0;
	deal();/*处理证词*/
	for(i=1;i<=n;i++)/*质疑罪犯*/
	{
		if(handle(i))
		{
			if(flag)
			{
				printf("Cannot Determine\n");
				return 0;
			}
			flag=i;
		}
	}
	if(!flag)
	{
		printf("Impossible\n");
		return 0;
	}
	else
	{
		printf("%s",names[flag]+1);
		return 0;
	}
	return 0;
}



数据零:

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


数据一:

1 0 2
A
A: I am guilty.
A: I am not guilty.

数据二:

5 1 5
A
B
C
D
E
A: Today is Monday.
B: Today is Thursday.
C: Today is Monday.
B: D is not guilty.
E: I am not guilty.

数据三:

7 3 10
MONDAY
TUESDAY
WEDNESDAY
THURSDAY
FRIDAY
SATURDAY
SUNDAY
MONDAY: Today is Monday.
TUESDAY: Today is Tuesday.
WEDNESDAY: Today is Wednesday.
THURSDAY: Today is Thursday.
FRIDAY: MONDAY is not guilty.
FRIDAY: TUESDAY is not guilty.
FRIDAY: WEDNESDAY is not guilty.
FRIDAY: THURSDAY is not guilty.
SATURDAY: SUNDAY is not guilty.
SUNDAY: SATURDAY is not guilty.

数据四:

4 1 5
KYO
IORI
CHIZURU
OROCHI
KYO: I am guilty.
IORI: I am not guilty.
CHIZURU: OROCHI is guilty.
OROCHI: Today is Monday.
OROCHI: I am guilty.

数据五:

10 7 20
A
AA
AAA
AAAA
AAAAA
AAAAAA
AAAAAAA
AAAAAAAA
AAAAAAAAA
AAAAAAAAAA
A: Today is Monday.
AA: Today is Monday.
AAA: Today is Monday.
AAAA: Today is Monday.
AAAAA: Today is Monday.
AAAAAA: Today is Monday.
AAAAAAA: Today is Monday.
AAAAAAAA: Today is Sunday.
AAAAAAAAA: Today is Sunday.
AAAAAAAAAA: Today is Sunday.
AAAAAAAAAA: AAA is not guilty.
AAAAAAAAA: A is not guilty.
AAAAAAAA: AAAAA is not guilty.
AAAAAAA: AAAAAA is guilty.
AAAAAA: AAAAAAAAAA is guilty.
AAAAA: AAAAAAAA is guilty.
AAAA: AAAAAAA is guilty.
AAA: AA is guilty.
AA: AAAAAAAAA is guilty.
A: AAAAA is guilty.

数据六:

1 1 2
ALAN
ALAN: I am not guity.
ALAN: I am not not guity.

数据七:

3 3 3
SAM
SANDY
SUE
SAM: I am not guity. Am I???
SUE: SANDY is guity.
SANDY: SUE is guity.

数据八:

10 10 10
A
B
C
D
E
F
G
H
I
J
A: B is guilty.
B: C is guilty.
C: D is guilty.
D: E is guilty.
E: F is guilty.
F: G is guilty.
G: H is guilty.
H: I love you!
I: I am not guilty.
J: I is not guilty.

数据九:

1 0 3
CENGJINGYOUYIDUANZHENZHIDEGANQINGFANGZAIWOMIANQIANWOMEIYOUZHENXIDENGDAOSHIQULEYIHOUCAIZHUIHUIMOJIRENSHIJIANZUITONGKUDESHIMOGUOYUCIRUGUOSHANGTIANNENGGEIWOYIGEZAILAIYICIDEJIHUIWOHUIDUINAGENVHAIZISHUOSANGEZI
CENGJINGYOUYIDUANZHENZHIDEGANQINGFANGZAIWOMIANQIANWOMEIYOUZHENXIDENGDAOSHIQULEYIHOUCAIZHUIHUIMOJIRENSHIJIANZUITONGKUDESHIMOGUOYUCIRUGUOSHANGTIANNENGGEIWOYIGEZAILAIYICIDEJIHUIWOHUIDUINAGENVHAIZISHUOSANGEZI: I love you!
CENGJINGYOUYIDUANZHENZHIDEGANQINGFANGZAIWOMIANQIANWOMEIYOUZHENXIDENGDAOSHIQULEYIHOUCAIZHUIHUIMOJIRENSHIJIANZUITONGKUDESHIMOGUOYUCIRUGUOSHANGTIANNENGGEIWOYIGEZAILAIYICIDEJIHUIWOHUIDUINAGENVHAIZISHUOSANGEZI: If there must be a deadline,
CENGJINGYOUYIDUANZHENZHIDEGANQINGFANGZAIWOMIANQIANWOMEIYOUZHENXIDENGDAOSHIQULEYIHOUCAIZHUIHUIMOJIRENSHIJIANZUITONGKUDESHIMOGUOYUCIRUGUOSHANGTIANNENGGEIWOYIGEZAILAIYICIDEJIHUIWOHUIDUINAGENVHAIZISHUOSANGEZI: I hope it is 10000 years!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值