题目描述
明明同学最近迷上了侦探漫画《柯南》并沉醉于推理游戏之中,于是他召集了一群同学玩推理游戏。游戏的内容是这样的,明明的同学们先商量好由其中的一个人充当罪犯(在明明不知情的情况下),明明的任务就是找出这个罪犯。接着,明明逐个询问每一个同学,被询问者可能会说:
证词中出现的其他话,都不列入逻辑推理的内容。
明明所知道的是,他的同学中有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;
}