noip2003 偵探推理 終極模擬

題目描述

明明同學最近迷上了偵探漫畫《柯南》並沉醉於推理遊戲之中,於是他召集了一羣同學玩推理遊戲。遊戲的內容是這樣的,明明的同學們先商量好由其中的一個人充當罪犯(在明明不知情的情況下),明明的任務就是找出這個罪犯。接着,明明逐個詢問每一個同學,被詢問者可能會說:

證詞中出現的其他話,都不列入邏輯推理的內容。

明明所知道的是,他的同學中有N個人始終說假話,其餘的人始終說真。

現在,明明需要你幫助他從他同學的話中推斷出誰是真正的兇手,請記住,兇手只有一個!

 

輸入

輸入由若干行組成,第一行有二個整數,M(1≤M≤20)、N(1≤N≤M)和P(1≤P≤100);

M是參加遊戲的明明的同學數,N是其中始終說謊的人數,P是證言的總數。接下來M行,

每行是明明的一個同學的名字(英文字母組成,沒有主格,全部大寫)。

往後有P行,每行開始是某個同學的名宇,緊跟着一個冒號和一個空格,後面是一句證詞,符合前表中所列格式。證詞每行不會超過250個字符。

    輸入中不會出現連續的兩個空格,而且每行開頭和結尾也沒有空格。

輸出

如果你的程序能確定誰是罪犯,則輸出他的名字;如果程序判斷出不止一個人可能是

罪犯,則輸出 Cannot Determine;如果程序判斷出沒有人可能成爲罪犯,則輸出 Impossible。

樣例輸入

2 2 4HELLOGUILTYHELLO: What is your name?GUILTY: I am GUILTY.GUILTY: Are you guilty?HELLO: I am not guilty.

樣例輸出

HELLO

思路就是枚舉星期幾那麼就可以推理出來了,其他的...自己看吧,去年寫的...
#include<map>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
map<string,int>Map;
int num[105],f[21],m,n,i,j,k,p,flag,now,lie,len,cnt,today,t;
char a[21][205],name[105][205],s[105][21][205],ans[101][205];
char day[8][25]={" ","Monday.","Tuesday.","Wednesday.","Thursday.","Friday.","Saturday.","Sunday."};
bool cmp(char *a,char *b)
{
    int l1=strlen(a),l2=strlen(b);
    if(l1!=l2)return false;
    for(int i=0;i<l1;i++)if(a[i]!=b[i])return false;
    return true;
}
int check1(int k)
{
    if(!cmp(s[k][num[k]],"guilty.")||(num[k]!=3&&num[k]!=4))return 2;
    if(s[k][1][0]!='I'||s[k][1][1]!='\0'||!cmp(s[k][2],"am"))return 2;
    if(num[k]==4&&!cmp(s[k][3],"not"))return 2;
    if(Map[name[k]]==now)return num[k]!=3;
    return num[k]==3;
}
int check2(int k)
{
    if(!cmp(s[k][num[k]],"guilty.")||(num[k]!=3&&num[k]!=4||!cmp(s[k][2],"is")))return 2;
    if(num[k]==4&&!cmp(s[k][3],"not"))return 2;
    if(Map[s[k][1]]==now)return num[k]!=3;
    return num[k]==3;
}
int check3(int k)
{
    if(num[k]!=3||!cmp(s[k][1],"Today")||!cmp(s[k][2],"is"))return 2;
    return !cmp(day[today],s[k][3]);
}
int work()
{
    now=Map[a[p]];
    int r=0,another=0;
    memset(f,0,sizeof(f));
    for(int i=1;i<=m;i++)
    {
        int t1=check1(i),t2=check2(i),t3=check3(i),pre=Map[name[i]];
        if(!t1||!t2||!t3)
        {
            if(f[pre]==2)return 0;
            f[pre]=1;
        }
        if(t1&1||t2&1||t3&1)
        {
            if(f[pre]==1)return 0;
            f[pre]=2;
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(f[i]==2)r++;
        else if(!f[i])another++;
    }
    return (r<=lie&&r+another>=lie);
}
int main()
{
    cin>>n>>lie>>m;
    for(i=1;i<=n;i++)
    {
        cin>>a[i];
        Map[a[i]]=i;
    }
    for(i=1;i<=m;i++)
    {
        cin>>name[i];
        name[i][strlen(name[i])-1]='\0';
        num[i]=1;
        cin>>s[i][num[i]];
        while(isalpha((s[i][num[i]][strlen(s[i][num[i]])-1])))cin>>s[i][++num[i]];
    }
    for(p=1;p<=n;p++)
    {
        flag=0;
        for(today=1;today<=7&&!flag;today++)flag=work();
        if(flag)memcpy(ans[++cnt],a[p],sizeof(a[p]));
    }
    if(!cnt)cout<<"Impossible";
    else if(cnt==1)cout<<ans[cnt];
    else cout<<"Cannot Determine";
    return 0;
}


發佈了36 篇原創文章 · 獲贊 25 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章