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

时间:2022-12-16 19:20:01
P1106侦探推理

描述

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

明明所知道的是,他的同学中有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 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

限制

每个测试点1s

提示

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

来源

NOIP2003第二题


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

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define max_m 20
#define max_p 100
#define max_len 250
using 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;
}