【NOIP 2003提高】侦探推理 模拟

来源:互联网 发布:色诺芬经济金融数据库 编辑:程序博客网 时间:2024/05/01 07:03

题目描述

  明明同学最近迷上了侦探漫画《柯南》并沉醉于推理游戏之中,于是他召集了一群同学玩推理游戏。游戏的内容是这样的,明明的同学们先商量好由其中的一个人充当罪犯(在明明不知情的情况下),明明的任务就是找出这个罪犯。接着,明明逐个询问每一个同学,被询问者可能会说: 这里写图片描述
  证词中出现的其他话,都不列入逻辑推理的内容。
  明明所知道的是,他的同学中有N个人始终说假话,其余的人始终说真。
  现在,明明需要你帮助他从他同学的话中推断出谁是真正的凶手,请记住,凶手只有一个!

数据范围

1≤M≤20
1≤N≤M
1≤P≤100

样例输入

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??

样例输出

MIKE

解题思路

枚举凶手与日期判断即可。注意如果一个人说的全是被忽略的话,也可以把他当做说谎的人。

代码

#include <bits/stdc++.h>using namespace std;inline int Getint(){int x=0,f=1;char ch=getchar();while('0'>ch||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}inline string Getname(){string s="";char ch=getchar();while(!isalpha(ch))ch=getchar();while(isalpha(ch))s+=ch,ch=getchar();return s;}inline string Getline(){    string s="";    char ch=getchar();    while(!isalpha(ch))        ch=getchar();    while(ch!='\n'){        s+=ch;        ch=getchar();        if(ch==-1)break;//不知道为什么,交我们学校OJ必须要加这一句话。。。不然读入卡死    }    return s;}inline string Splitname(string s){string ret="";for(int i=0;s[i]!=':';i++)ret+=s[i];return ret;}inline string Splitword(string s){string ret="";int p=0;while(s[p]!=':')p++;for(p++;p<s.length();p++)ret+=s[p];return ret;}string name[25];string w[8]={""," Today is Monday."," Today is Tuesday."," Today is Wednesday."," Today is Thursday."," Today is Friday."," Today is Saturday."," Today is Sunday.",};string e[2]={" I am guilty."," I am not guilty."};string s[105];map<string,int>Map;int vis[105],fail;int Check1(string s){    if(s.length()<13)return 0;    string tmp=s.substr(s.length()-11,11);    if(tmp!=" is guilty.")return false;    tmp=s.substr(1,s.length()-12);    return Map[tmp];}int Check2(string s){    if(s.length()<17)return 0;    string tmp=s.substr(s.length()-15,15);    if(tmp!=" is not guilty.")return false;    tmp=s.substr(1,s.length()-16);    return Map[tmp];}void Change(int x,bool t){    if(t&&vis[x]==2)fail=1;    if(!t&&vis[x]==1)fail=1;    if(t)vis[x]=1;    if(!t)vis[x]=2;}int main(){    int m=Getint(),n=Getint(),p=Getint(),Ans=0;    for(int i=1;i<=m;i++)Map[name[i]=Getname()]=i;    for(int i=1;i<=p;i++)s[i]=Getline();    for(int i=1;i<=m;i++){        for(int j=1;j<=7;j++){            fail=0;            memset(vis,0,sizeof(vis));            int t,tot=0;            for(int k=1;k<=p;k++){                string Name=Splitname(s[k]);                string word=Splitword(s[k]);                for(int l=1;l<=7;l++)if(word==w[l])Change(Map[Name],l==j);                if(word==e[0])Change(Map[Name],i==Map[Name]);                if(word==e[1])Change(Map[Name],i!=Map[Name]);                t=Check1(word);                if(t)Change(Map[Name],t==i);                t=Check2(word);                if(t)Change(Map[Name],t!=i);            }            for(int k=1;k<=m;k++)                if(vis[k]==2)                    tot++;            int tot2=0;            for(int k=1;k<=m;k++)                if(!vis[k])                    tot2++;            if(fail||tot>n||tot+tot2<n)continue;            if(Ans!=i&&Ans){                cout<<"Cannot Determine\n";                exit(0);            }            Ans=i;        }    }    if(!Ans)cout<<"Impossible\n";    else cout<<name[Ans];    return 0;}
0 0
原创粉丝点击