noip2003 侦探推理 (字符串处理)

来源:互联网 发布:法医知乎 编辑:程序博客网 时间:2024/05/01 15:02
P1106侦探推理
Accepted
标签:字符串模拟NOIP提高组2003

描述

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

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

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

格式

输入格式

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

输入中不会出现连续的两个空格,而且每行开头和结尾也没有空格。

输出格式

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

样例1

样例输入1[复制]

3 1 5MIKECHARLESKATEMIKE:I am guilty.MIKE:Today is Sunday.CHARLES:MIKE is guilty.KATE:I am guilty.KATE:How are you??

样例输出1[复制]

MIKE

限制

每个测试点1s

提示

有说一句话的末尾无空格的么?..

来源

NOIP2003第二题


解析:直接枚举凶手是谁,今天星期几,然后判断是否合法即可。根据合法的情况数,得到答案。

代码:

#include<cstdio>#include<cstring>#include<algorithm>#define max_m 20#define max_p 100#define max_len 250using namespace std;int m,n;char name[max_m+20][max_len+20];struct tnode{int x,xq;             bool y[max_m+20];            }person[max_m+20];char zy[5][30]={"I am guilty.","I am not guilty.","is guilty.","is not guilty.","Today is "};char day[8][20]={"-_-||","Monday.","Tuesday.","Wednesday.","Thursday.","Friday.","Saturday.","Sunday."};int lz[5]={12,16,10,14,9};int ld[8]={0,7,8,10,9,7,9,7};int ln[max_m+20];bool used[max_m+20],f[max_m+20];bool jia[max_m+20];void readdata(){  int i,j,k,p,len,l,r;  char s[max_len+20];    scanf("%d%d%d\n",&m,&n,&p);  for(i=1;i<=m;i++)gets(name[i]),ln[i]=strlen(name[i]);  for(i=1;i<=m;i++)person[i].x=person[i].xq=0;    for(i=1;i<=p;i++)    {      gets(s),len=strlen(s);            for(r=0;r<len && s[r]!=':';r++);      for(j=1;j<=m;j++)        if(strncmp(name[j],s,r)==0)break;      if(j>m || used[j])continue;            l=r+2,r=l;      //check 0      if(strncmp(zy[0],s+l,lz[0])==0)        {          if(person[j].y[j] && (person[j].x!=0 && person[j].x!=j))used[j]=1;          person[j].x=j;  f[j]=1;  continue;              }      //check 1  if(strncmp(zy[1],s+l,lz[1])==0)    {      if(person[j].x==j)used[j]=1;      person[j].y[j]=1;      f[j]=1;      continue;    }  //注意有人叫 Today 的情况    //check 4  if(strncmp(zy[4],s+l,lz[4])==0)    {      for(l+=lz[4],k=1;k<=7;k++)        if(strncmp(s+l,day[k],ld[k])==0)break;      if(k<=7)    {      if(person[j].xq!=0 && person[j].xq!=k)used[j]=1;      person[j].xq=k;      f[j]=1;      continue;    }      }    for(;r<len && s[r]!=' ';r++);  for(k=1;k<=m;k++)     if(ln[k]==r-l && strncmp(name[k],s+l,r-l)==0)break;      if(k>m)continue;    l=r+1;  //check 2  if(strncmp(s+l,zy[2],lz[2])==0)    {      if(person[j].y[k] || (person[j].x!=0 && person[j].x!=k))used[j]=1;      person[j].x=k;      f[j]=1;      continue;    }  //check 3  if(strncmp(s+l,zy[3],lz[3])==0)    {      if(person[j].x==k)used[j]=1;      person[j].y[k]=1;      f[j]=1;    }      }}int get(int xx,int yy){  memset(jia,0,sizeof(jia));  int i,j,k,sum=0;  for(i=1;i<=m;i++)if(!used[i]  && f[i])    {      if(person[i].x!=0 && person[i].x!=xx)    {  jia[i]=1,sum++;  continue;}      if(person[i].xq!=0 && person[i].xq!=yy)    {  jia[i]=1,sum++;  continue;}      if(person[i].y[xx])    jia[i]=1,sum++;    }  for(i=1;i<=m;i++)if(jia[i])    {      if(person[i].x==xx || person[i].xq==yy)return 30;      for(j=1;j<=m;j++)if(j!=xx && person[i].y[j])return 30;    }  return sum;}void work(){  int i,j,k,s1,s2,ans=0;  for(s1=0,i=1;i<=m;i++)if(!f[i])s1++;    for(i=1;i<=m;i++)if(!used[i])    for(j=1;j<=7;j++)      {        s2=get(i,j);        if(s2<=n && n<=s2+s1)          {            if(ans!=0)              {                printf("Cannot Determine\n");                return;              }            ans=i; break;           }      }  if(ans==0)printf("Impossible\n");  else printf("%s\n",name[ans]);      }int main(){  readdata();  work();  return 0;}


0 0
原创粉丝点击