• 【b302】侦探推理


    Time Limit: 1 second
    Memory Limit: 50 MB

    【问题描述】

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

    证词中出现的其他话,都不列入逻辑推理的内容。 明明所知道的是,他的同学中有N个人始终说假话,其余的人始终说真。 现在,明明需要你帮助他从他同学的话中推断出谁是真正的凶手,请记住,凶手只有一个!

    【输入】

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

    【输出】

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

    【输入样例】

    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
    

    【题目链接】:http://noi.qz5z.com/viewtask.asp?id=b302

    【题意】

    【题解】

    题目描述不清啊
    可以确定凶手的有两种情况
    一种是确定m-1个人不是凶手。
    另外一种是确定了一个人是凶手。
    这里impossible的情况有两种
    一种是全都不是凶手,另外一种就是无法达到满足的要求,即N个人说谎然后P条话都不冲突;
    然后无法确定的就是剩余的;
    有点迷。
    不用理这种题。
    (冒号后面还有一个空格。。。)
    O(2^m)*p爆搜就好

    【完整代码】

    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <string>
    #include <iostream>
    #include <map>
    #include <cstring>
    using namespace std;
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define LL long long
    #define rep1(i,a,b) for (int i = a;i <= b;i++)
    #define rep2(i,a,b) for (int i = a;i >= b;i--)
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define rei(x) scanf("%d",&x)
    #define rel(x) scanf("%lld",&x)
    
    typedef pair<int, int> pii;
    typedef pair<LL, LL> pll;
    
    const int dx[9] = { 0,1,-1,0,0,-1,-1,1,1 };
    const int dy[9] = { 0,0,0,-1,1,-1,1,-1,1 };
    const double pi = acos(-1.0);
    const int N = 20+10;
    const int P = 100 + 50;
    
    struct abc
    {
        int  id, who,author;
        int xingqi;
    };
    
    int m, n, p,tot,ma = 0;
    bool bo[N],is[N],notis[N],xingqi[N];
    string name[N];
    string t;
    char ts[300];
    abc xinxi[P];
    map <string, int> dic;
    map <string, int> dic2;
    
    void sear_ch()
    {
        int today = -1;
        memset(xingqi, true, sizeof xingqi);
        memset(is, false, sizeof is), memset(notis, false, sizeof notis);
        rep1(i, 1, tot)
        if (bo[xinxi[i].author])
        {
            if (xinxi[i].id == 2)
            {
                if (today == -1)
                {
                    if (!xingqi[xinxi[i].xingqi]) return;
                    today = xinxi[i].xingqi;
                }
                else
                {
                    if (today != xinxi[i].xingqi)
                        return;
                }
            }
            else
            {
                int y = xinxi[i].who;
                if (xinxi[i].id == 0)
                {
                    if (is[y])
                        return;
                    notis[y] = true;
                }
                else
                {
                    if (notis[y])
                        return;
                    is[y] = true;
                }
            }
        }
        else
            if (!bo[xinxi[i].author])
            {
                if (xinxi[i].id == 2)
                {
                    if (today == xinxi[i].xingqi)
                        return;
                    xingqi[xinxi[i].xingqi] = false;
                }
                else
                {
                    int y = xinxi[i].who;
                    if (xinxi[i].id == 0)
                    {
                        if (notis[y])
                            return;
                        is[y] = true;
                    }
                    else//说y是凶手
                    {
                        if (is[y])
                            return;
                        notis[y] = true;
                    }
                }
            }
        int cnt = 0,j = -1,cntnot = 0;
        rep1(i, 1, m)
        {
            if (is[i])
                cnt++, j = i;
            if (notis[i])
                cntnot++;
        }
        if (cnt == 1)
        {
            cout << name[j] << endl;
            exit(0);
        }
        if (cntnot == m - 1)
        {
            rep1(i, 1, m)
                if (!notis[i])
                    cout << name[i] << endl;
            exit(0);
        }
        if (cntnot == m)
            puts("Impossible");
        else
            puts("Cannot Determine");
        exit(0);
    }
    
    void dfs(int x, int now)
    {
        if (x > m)
        {
            if (now == n)
            {
                sear_ch();
            }
            return;
        }
        bo[x] = false;
        dfs(x + 1, now + 1);
        bo[x] = true;
        dfs(x + 1, now);
    }
    
    int main()
    {
        //freopen("F:\rush.txt", "r", stdin);
        memset(bo, true, sizeof bo);
        dic2["Monday"] = 1, dic2["Tuesday"] = 2, dic2["Wednesday"] = 3, dic2["Thursday"] = 4;
        dic2["Friday"] = 5, dic2["Saturday"] = 6, dic2["Sunday"] = 7;//处理出星期对应的数字
        rei(m), rei(n), rei(p);
        rep1(i, 1, m)
        {
            cin >> name[i];
            dic[name[i]] = i;//为每个名字搞hash对应到它的标号
        }
        char tt = getchar();
        rep1(i, 1, p)
        {
            cin.getline(ts, 300);
            t = string(ts);
            t += ' ';//在末尾加上一个空格,方便获取信息
            int po = t.find(':', 0);
            string who = t.substr(0, po);//把说话的人提取出来
            t.erase(0, po + 2);//把说话人和冒号去掉
            string s[5];
            rep1(j, 1, 4)//只找前4个单词
            {
                s[j] = "";
                if (t == "")
                {
                    rep1(k, j + 1, 4) s[k] = "";
                    break;//空掉了就结束
                }
                po = t.find(' ', 0);
                s[j] = t.substr(0, po);//否则把那个单词搞出来
                t.erase(0, po + 1);//连同空格删掉
            }
            if (s[3] == "") continue;//如果没有3个单词肯定不是信息
            if (s[1] == "I" && s[2] == "am" && s[3] == "guilty.")
                xinxi[++tot].who = dic[who],xinxi[tot].id = 1,xinxi[tot].author = dic[who];
            if (s[1] == "I" && s[2] == "am" && s[3] == "not" && s[4]== "guilty.")
                xinxi[++tot].who = dic[who], xinxi[tot].id = 0, xinxi[tot].author = dic[who];
            if (s[2] == "is" && s[3] == "guilty.")
                xinxi[++tot].who = dic[s[1]], xinxi[tot].id = 1, xinxi[tot].author = dic[who];
            if (s[2] == "is" && s[3] == "not" && s[4] == "guilty.")
                xinxi[++tot].who = dic[s[1]], xinxi[tot].id = 0, xinxi[tot].author = dic[who];
            if (s[4] != "") continue;
            s[3].erase(int(s[3].size()) - 1, 1);
            if (s[1] == "Today" && s[2] == "is" && dic2[s[3]])
                xinxi[++tot].id = 2, xinxi[tot].xingqi = dic2[s[3]],xinxi[tot].author = dic[who];
        }
        dfs(1, 0);
        puts("Impossible");
        return 0;
    }
  • 相关阅读:
    斜率dp+cdq分治
    踢罐子 [几何+乱搞]
    [HDU3710] Battle Over Cities [树链剖分+线段树+并查集+kruskal+思维]
    [xsy1129] flow [树链剖分和线段树一起优化网络流][我也不知道这是什么鬼标签]
    [CF666E] Forensic Examination [广义后缀自动机+线段树合并]
    省选算法学习-BSGS与exBSGS与二次剩余
    省选算法学习-回文自动机 && 回文树
    省选算法学习-后缀数组+后缀自动机+后缀树
    Password [分块]
    随机过程——泊松过程
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626570.html
Copyright © 2020-2023  润新知