zoukankan      html  css  js  c++  java
  • P1039 侦探推理

    题目描述

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

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

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

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

    输入输出格式

    输入格式:

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

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

    往后有P行,每行开始是某个同学的名宇,紧跟着一个冒号和一个空格,后面是一句证词,符合前表中所列格式。证词每行不会超过250个字符。

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

    输出格式:

    如果你的程序能确定谁是罪犯,则输出他的名字;如果程序判断出不止一个人可能是罪犯,则输出 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


    //记录每一句话是谁说的以及这句话的内容
    //可以用map存人名对应的下标 
    
    //我们枚举每一个人i,假设i是罪犯
    //然后枚举今天是星期几,用day表示 
    //然后判断有没有矛盾
    
    //如何判断?
    //进行每一次判断的时候,先使所有人的状态不确定,也就是不知道他们会说真话假话
    //TF[a]==-1是不确定,TF[a]=1是说真话,TF[a]=0是说假话
    //T是说真话的人数,F是说假话的人数 
    //设罪犯为 i 
    //设flag为这句话是真话还是假话,flag=1是真话,flag=0是假话 
    //id是说这句话的人 
    //枚举每一句话
    //    看一下id以前的状态,如果状态不确定(TF==-1),就TF[id]=flag
    //    否则,如果和以前状态一样(TF[id]==flag),就没有矛盾,
    //    TF[id]!=flag就是出现了矛盾(因为一个人始终直说一种话),判断不出来了,直接return去枚举下一个人是罪犯 
    //如果F>n或者T>m-n了,也就是说假话的人数超过了题目中给的人数,矛盾,return
    //如果找到了不止一个罪犯,输出"Cannot Determine",直接exit(0) 
    
    //怎么知道这句话是真话假话? 
    //①如果话里有 "I am guilty."
    //    那么看一下id是不是i,不是的话,就是在说假话
    //②话里有"I am not guilty"
    //    看一下id是不是i,不是的话,就是在说真话,否则就是假话 
    //③话里有"xxx is guilty"
    //    如果xxx是i的话,就是真话,否则是假话
    //④话里有"xxx is not guilty"
    //    如果xxx不是i的话,就是真话,否则是假话
    //⑤话里有"Today is XXX"
    //    如果xxx与day一样,就是真话,否则是假话
     
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<map>
    #include<algorithm>
    using namespace std;
    
    string S[10]=
    {
        "Today is Sunday.",
        "Today is Monday.",
        "Today is Tuesday.",
        "Today is Wednesday.",
        "Today is Thursday.",
        "Today is Friday.",
        "Today is Saturday.",
    };
    
    int m,n,p;
    int T,F,ans;
    int TF[25];
    struct Sen
    {
        int id;
        string s;
    }sen[105];
    map<string,int> ma;
    
    bool judgeTF(int id,bool flag)    //看一下有没有冲突,return 1 表示有冲突 
    {
        if(TF[id]==-1)        //状态不确定 
        {
            TF[id]=flag;    //赋状态 
            if(flag)    //说真话的人数++ 
                ++T;
            else    //说假话的人数++ 
                ++F;
        }
        else
            return TF[id]!=flag;    //和之前的一不一样,一样返回0,不一样返回1 
        if(F>n||T>m-n)    //说假话的人比n多或者是说真话的人比m-n多 
            return 1;
        return 0;
    }
    
    void judge(int id,string day)
    {
        memset(TF,-1,sizeof(TF));    //所有人都不知道说的是真话假话 
        T=F=0;        //说真话、假话人数置0 
        string tmp;
        for(int i=1;i<=p;++i)
        {
            int pos=sen[i].s.find("I am guilty.");    //pos为-1则没说这句话 
            if(~pos)
            {
                if(judgeTF(sen[i].id,sen[i].id==id))    //因为我们假设了id是罪犯,所以不是id的人就不是罪犯,就是在说假话
                    return;
            }
            pos=sen[i].s.find("I am not guilty");
            if(~pos)
            {
                if(judgeTF(sen[i].id,sen[i].id!=id))
                    return;
            }
            pos=sen[i].s.find(" is guilty.");
            if(~pos)
            {
                tmp=sen[i].s;
                tmp.erase(pos,11);
                if(judgeTF(sen[i].id,ma[tmp]==id))
                    return;
            }
            pos=sen[i].s.find(" is not guilty.");
            if(~pos)
            {
                tmp=sen[i].s;
                tmp.erase(pos,15);
                if(judgeTF(sen[i].id,ma[tmp]!=id))
                    return;
            }
            pos=sen[i].s.find("Today is ");
            if(~pos)
            {
                if(judgeTF(sen[i].id,sen[i].s==day))
                    return;
            }
        }
        if(ans&&ans!=id)    //找到了不止一个罪犯 
        {
            puts("Cannot Determine");    //不能确定 
            exit(0);
        }
        ans=id;        //id是罪犯 
    }
    
    string s[25],name,a;
    int main()
    {
        scanf("%d%d%d",&m,&n,&p);
        for(int i=1;i<=m;++i)
        {
            cin>>s[i];
            ma[s[i]]=i;        //存名字标号 
        }
        for(int i=1;i<=p;++i)
        {
            cin>>name;        //输入说话者 
            name.erase(name.length()-1,1);        //把后边的冒号搞掉 
            getline(cin,a);
            a.erase(0,1);    //把前边的空格搞掉 
            if(a[a.length()-1]=='
    '||a[a.length()-1]=='
    ')    //把坑爹的换行符搞掉 
                a.erase(a.length()-1,1);
            sen[i].id=ma[name];        //存说话者 
            sen[i].s=a;        //存说话内容 
        }
        for(int i=1;i<=m;++i)    //假设第i个人是罪犯 
            for(int j=0;j<7;++j)    //假设今天是S[j]天 
                judge(i,S[j]);
        if(!ans)    //找不到罪犯 
            puts("Impossible");
        else
            cout<<s[ans];    //罪犯名字 
        return 0;
    }
  • 相关阅读:
    13 110内容回、111内容回顾、redis操作
    11 git第二部分(未完成)
    10 内容回顾和补充、分页加密
    09 深科技相关表结构 (未完成)、git
    $ python manage.py makemigrations You are trying to add a non-nullable field 'name' to course without a default; we can't do that (the database needs something to populate existing rows). Please selec
    6、DockerFile解析:三步走、保留字指令
    Linux 中各个文件夹的作用
    H.264 Profile-level-id
    H.264编码profile & level控制
    H.264分层结构与码流结构
  • 原文地址:https://www.cnblogs.com/lovewhy/p/8665999.html
Copyright © 2011-2022 走看看