0
点赞
收藏
分享

微信扫一扫

P1039 [NOIP2003 提高组] 侦探推理

深夜瞎琢磨 2022-04-15 阅读 62
c++

题目描述

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

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

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

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

输入格式

输入由若干行组成,第一行有三个整数,M(1≤M≤20)M(1≤M≤20)、N(1≤N≤M)N(1≤N≤M)和P(1≤P≤100)P(1≤P≤100);MM是参加游戏的明明的同学数,NN是其中始终说谎的人数,PP是证言的总数。

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

往后有PP行,每行开始是某个同学的名宇,紧跟着一个冒号和一个空格,后面是一句证词,符合前表中所列格式。证词每行不会超过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

说明/提示

【题目来源】

NOIP 2003 提高组第二题


链接拿来!!

[NOIP2003 提高组] 侦探推理 - 洛谷

好的,这道题是一道提高+/省选-的题

一看我就害怕了,害得我在编程环境里试了12遍

还好是过了

代码:

#include <iostream>
#include <cstring>
const int MaxNameLength=250;
const int MaxSayLen=250;
const int MaxWordNum=20;
const int WeekNum=7;
void printArray(int** priceArray,int len,int len2) {
	for(int i=0; i<len; i++) {
		for(int j=0; j<len2; j++) {
			printf("%d\t",priceArray[i][j]);
		}
		printf("\n");
	}
	printf("\n");

}
void printArray2(int* priceArray,int len) {
	for(int i=0; i<len; i++) {
		printf("%d\t",priceArray[i]);
	}
	printf("\n");

}
int findName(char** name,int len,char* find) {
	for(int i=0; i<len; i++) {
		if(strcmp(name[i],find)==0) {
			return i;
		}
	}
	return -1;
}
int main() {
	int m,n,p;

	int i,j;
	scanf("%d %d %d",&m,&n,&p);
	char** name=new char*[m];

	for(i=0; i<m; i++) {
		name[i]=new char[MaxNameLength];
		scanf("%s",name[i]);
	}

	int** says=new int*[p];
	int wordnum;
	int wordlen;
	char temp[MaxWordNum][MaxSayLen];

	char ch='\n';

	char guilty[10]="guilty";
	char today[6]="Today";
	char I[10]="am";
	char week[WeekNum][12]= {"monday","tuesday","wednesday","thursday","friday","saturday","sunday"};

	int len=0;
	for(i=0; i<p; i++) {
		wordnum=0;
		wordlen=0;
		while (ch=='\n'||ch==EOF||ch=='\r') {
			ch=getchar();
		}
		while (ch!='\n'&&ch!=EOF&&ch!='\r') {
			if(ch==' ') {
				temp[wordnum][wordlen]='\0';
				wordlen=0;
				wordnum++;
			} else if((ch>='A'&&ch<='Z')||(ch>='a'&&ch<='z')) {
				temp[wordnum][wordlen]=ch;
				wordlen++;
			}
			ch=getchar();
		}
		temp[wordnum][wordlen]='\0';
		for(j=0; j<wordlen; j++) {
			char c=temp[wordnum][j];
			if(c>='A'&&c<='Z') {
				temp[wordnum][j]=c-'A'+'a';
			}
		}
		wordlen=0;
		wordnum++;
		if(strcmp(temp[wordnum-1],guilty)==0) {
			int sayIndex=findName(name,m,temp[0]);
			int mbIndex;
			if(sayIndex>=0) {
				says[len]=new int[3];
				if(strcmp(temp[2],I)==0) {
					mbIndex=sayIndex;
				} else {
					mbIndex=findName(name,m,temp[1]);
				}
				if(mbIndex>=0) {
					says[len][0]=sayIndex;
					says[len][1]=mbIndex;
					if(wordnum>4) {
						says[len][2]=0;
					} else {
						says[len][2]=1;
					}
					len++;
				}

			}
		} else if(strcmp(temp[1],today)==0) {
			int sayIndex=findName(name,m,temp[0]);
			if(sayIndex>=0) {
				says[len]=new int[3];
				int mbIndex=-1;
				for(j=0; j<WeekNum; j++) {
					if(strcmp(temp[wordnum-1],week[j])==0) {
						mbIndex=j;
						break;
					}
				}
				if(mbIndex>=0) {
					says[len][0]=sayIndex;
					says[len][1]=-1;
					says[len][2]=mbIndex;
					len++;
				}
			}
		}
	}
	int* status=new int[m];
	int* search=new int[n];
	int* result=new int[m];
	int* weekResult=new int[WeekNum];
	int flag=-1;
	search[0]=0;
	i=0;
	int maxHead=m-n;
	while (search[0]<=maxHead) {
		if(i<n-1) {
			search[i+1]=search[i]+1;
			i++;
		} else {
			for(j=0; j<m; j++) {
				status[j]=1;
				result[j]=-1;
			}
			for(j=0; j<n; j++) {
				status[search[j]]=0;
			}

			for(j=0; j<WeekNum; j++) {
				weekResult[j]=-1;
			}
			int temp_flag=-2;
			for(j=0; j<len; j++) {
				if(says[j][1]>=0) {
					int temp_status=says[j][2]==status[says[j][0]];
					int index=says[j][1];
					int now_status=result[index];
					if(now_status==-1) {
						result[index]=temp_status;
					} else if(temp_status!=now_status) {
						temp_flag=-1;
						break;
					}
				} else {
					int index=says[j][0];
					int temp_status=status[index];
					int weekIndex=says[j][2];
					int now_status=weekResult[weekIndex];
					if(now_status==-1) {
						weekResult[weekIndex]=temp_status;
					} else if(temp_status!=now_status) {
						temp_flag=-1;
						break;
					}
				}

			}
			if(temp_flag!=-1) {
				int count=0;
				int count1=0;
				for(j=0; j<WeekNum; j++) {
					if(weekResult[j]==1) {
						count++;
					} else if(weekResult[j]==0) {
						count1++;
					}
				}
				if(count>1||count1>=WeekNum) {
					temp_flag=-1;
				}
			}
			if(temp_flag!=-1) {
				int count1=0;
				int index1=-1;
				int count2=0;
				int index2=-1;
				for(j=0; j<m; j++) {
					if(result[j]==1) {
						count1++;
						index1=j;
					} else if(result[j]==-1) {
						count2++;
						index2=j;
					}
				}

				if(count1>1) {
					temp_flag=-1;
				} else if(count1==1) {
					temp_flag=index1;
				} else if(count2>1) {
					temp_flag=-2;
				} else if(count2==1) {
					temp_flag=index2;
				}

				if(temp_flag>=0) {
					if(flag<0) {
						flag=temp_flag;
					} else if(flag!=temp_flag) {
						flag=-2;
						break;
					}
				} else {
					if(flag<0)
						flag=temp_flag;
				}
			}
			search[i]++;
			while (search[i]>m-n+i) {
				if(i==0) {
					break;
				}
				i--;
				search[i]++;

			}

		}
	}

	if(flag==-1) {
		printf("Impossible\n");
	} else if(flag==-2) {
		printf("Cannot Determine\n");
	} else {
		printf("%s\n",name[flag]);
	}

	for(i=0; i<m; i++) {
		delete name[i];
	}
	delete name;

	for(i=0; i<len; i++) {
		delete says[i];
	}
	delete says;

	delete status;
	delete search;
	delete result;
	return 0;
}
举报

相关推荐

0 条评论