【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!!!

### 回答1: NOIP2008 普及组复赛试题是中国国家信息学奥林匹克选手选拔赛的试题之一,比较经典且有一定难度。以下是对该试题的解答。 本次试题主要有三道题目,分别是小数排列、整数取位和检测型括号序列。 小数排列这道题要求给定一个正整数 n,求小于 n 的所有符合要求的小数的个数。解决这一题的方法是利用排列组合的知识,找出符合要求的小数的模式并计算其个数。具体的代码实现就需要对 n 进行拆分,计算个位数、十位数和百位数的可能情况并相乘即可得到结果。 整数取位这道题要求给定一个整数 n 和一个非负整数 m,求 n 的第 m 个数字。解决这一题的方法是将整数 n 转化为字符串,然后通过字符串的索引来获取第 m 个数字。 检测型括号序列这道题要求判断给定的一个仅包含左右括号的字符串是否是合法的括号序列。解决这一题的方法是使用栈的数据结构,遍历字符串,对于每个遇到的左括号,将其压入栈中;对于每个遇到的右括号,检查栈顶元素是否为对应的左括号,若是,则弹出栈顶元素,否则返回不合法。 以上就是对 NOIP2008 普及组复赛试题的简要解答,其中涉及到的算法和数据结构是编程中比较常见的基础知识,通过理解和掌握这些知识,可以帮助我们更好地解决类似的编程问题。 ### 回答2: NOIP(全国青少年信息学奥林匹克竞赛)是中国举办的一项信息学竞赛活动。2008年,NOIP举办了普及组复赛。以下是对该年度复赛试题进行的解答。 复赛试题一共有三大题目,分别涉及到图的遍历、数学运算和字符串处理。 第一题是关于图的遍历的。题目给出一张有向图和一个起始节点,要求按照拓扑排序的原则遍历整个图,并输出遍历的结果。拓扑排序是一种将有向无环图的顶点进行排序的算法,具体实现可以使用DFS或者BFS。根据题目给出的起始节点,我们可以使用DFS从该节点开始遍历图,并使用一个栈来存储遍历的结果。 第二题是一个数学运算的题目,要求计算一个给定数的乘方结果的各位数字之和。这题可以通过将给定数转化为字符串,然后对字符串中的每位数字进行相加来解答。也可以将给定数分解为各位数字相加的形式。具体实现上可以使用循环或者递归的方式。 第三题是一个关于字符串处理的任务,要求将输入字符串中的数字字符提取出来,并计算所有数字的平均值。这个问题可以通过遍历字符串的方式来解决。对于每个字符,我们判断是否为数字字符,是的话就将其转换为数字并累加到一个总和上。最后将总和除以数字字符的个数,得到平均值。 总体来说,NOIP 2008 普及组复赛试题涵盖了图的遍历、数学运算和字符串处理的内容。通过解答这些问题,可以增强对这些概念的理解,并提升解决实际问题的能力。 ### 回答3: NOIP2008普及组复赛试题是一道考察动态规划和递归思想的题目。题目给出了一个整数n,要求计算出整数1到n的所有排列中,满足以下条件的排列的个数: 1.相邻两个数的差的绝对值不能等于1; 2.排列中的数不能重复。 首先,我们需要定义一个函数f(n),表示整数1到n的满足条件的排列的个数。我们可以将这个问题转化为子问题,即如何计算f(n-1)和f(n-2)等。 根据题目要求,我们可以发现f(n)的值由两部分组成:一部分是以n结尾的满足条件的排列的个数,另一部分是不以n结尾的满足条件的排列的个数。 对于第一部分,即以n结尾的排列,我们可以将其分为两种情况:n和n-2相邻,以及n和n-2不相邻。如果n和n-2相邻,那么有f(n-2)种情况。如果n和n-2不相邻,那么可以在以n-1结尾的排列后面加上n,所以有f(n-1)种情况。因此,以n结尾的满足条件的排列的个数为f(n) = f(n-1) + f(n-2)。 对于第二部分,即不以n结尾的排列,其个数就是f(n-1)。 所以,f(n) = f(n-1) + f(n-2) + f(n-1) = 2*f(n-1) + f(n-2)。 基本情况是当n=1时,满足条件的排列只有1个,即f(1)=1;当n=2时,满足条件的排列有2个,即f(2)=2。 通过递推,可以得到整个解空间中满足条件的排列的个数。 在编程实现时,可以使用动态规划来解决这道题。先定义一个大小为n+1的数组dp,dp[i]表示整数1到i的满足条件的排列的个数。然后,通过循环从3到n,依次计算dp[i]的值,最后返回dp[n]即可。 总结起来,这道题是通过递推和动态规划的思想来计算满足条件的排列的个数。通过定义状态转移方程,将大问题转化为小问题,最后通过循环计算得出结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值