P1039 偵探推理
題目描述
明明同學最近迷上了偵探漫畫《柯南》並沈醉於推理遊戲之中,於是他召集了一群同學玩推理遊戲。遊戲的內容是這樣的,明明的同學們先商量好由其中的一個人充當罪犯(在明明不知情的情況下),明明的任務就是找出這個罪犯。接著,明明逐個詢問每一個同學,被詢問者可能會說:
證詞中出現的其他話,都不列入邏輯推理的內容。
明明所知道的是,他的同學中有NNN個人始終說假話,其余的人始終說真。
現在,明明需要你幫助他從他同學的話中推斷出誰是真正的兇手,請記住,兇手只有一個!
輸入輸出格式
輸入格式:輸入由若幹行組成,第一行有三個整數,M(1≤M≤20)M(1≤M≤20)M(1≤M≤20)、N(1≤N≤M)N(1≤N≤M)N(1≤N≤M)和P(1≤P≤100)P(1≤P≤100)P(1≤P≤100);MMM是參加遊戲的明明的同學數,NNN是其中始終說謊的人數,PPP是證言的總數。
接下來MMM行,每行是明明的一個同學的名字(英文字母組成,沒有空格,全部大寫)。
往後有PPP行,每行開始是某個同學的名宇,緊跟著一個冒號和一個空格,後面是一句證詞,符合前表中所列格式。證詞每行不會超過250250250個字符。
輸入中不會出現連續的兩個空格,而且每行開頭和結尾也沒有空格。
輸出格式:如果你的程序能確定誰是罪犯,則輸出他的名字;如果程序判斷出不止一個人可能是罪犯,則輸出 "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
Solution:
本題枚舉模擬,不過坑讀入。
處理出每句話的主人,枚舉當前天數和當前說謊的人,然後就是掃描話並標記每個人說話是否說謊就好了,若沒有沖突,就統計當前確定的說假話的人$cnt1$和不確定狀態的人個數$cnt2$,若$cnt1\leq n,cnt1+cnt2\geq n$就說明當前說謊的人可行,若多個人可行就多解。
代碼:
/*Code by 520 -- 9.2*/ #include<bits/stdc++.h> #define il inline #define ll long long #defineRE register #define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++) #define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--) using namespace std; const int N=105; int m,n,p,bl[N],f[N],ans; string id[N],say[N]; string day[8]={ " ","Today is Sunday.","Today is Monday.","Today is Tuesday.","Today is Wednesday.","Today is Thursday.","Today is Friday.","Today is Saturday." }; bool fail; il void check(int x,int y){ if(!f[x]) f[x]=y; else if(f[x]!=y) fail=1; } int main(){ ios::sync_with_stdio(false); cin>>m>>n>>p; For(i,1,m) cin>>id[i]; For(i,1,p) { cin>>say[i]; say[i].erase(say[i].end()-1); For(j,1,m) if(say[i]==id[j]) {bl[i]=j;break;} getline(cin,say[i]); say[i].erase(say[i].begin()); say[i].erase(say[i].end()-1); } For(d,1,7) For(la,1,m){ memset(f,0,sizeof(f)); fail=0; For(i,1,p){ RE int op=bl[i]; if(say[i]=="I am guilty.") check(op,op==la?1:-1); if(say[i]=="I am not guilty.") check(op,op==la?-1:1); For(j,1,7) if(say[i]==day[j]) check(op,d==j?1:-1); For(j,1,m) if(say[i]==id[j]+" is guilty.") check(op,j==la?1:-1); else if(say[i]==id[j]+" is not guilty.") check(op,j==la?-1:1); } if(fail)continue; int tot=0,sum=0; For(i,1,m) if(f[i]==-1) tot++;else if(!f[i]) sum++; if(tot<=n&&tot+sum>=n) { if(ans!=la&&ans)puts("Cannot Determine"),exit(0); ans=la; } } if(!ans) puts("Impossible"); else cout<<id[ans]; return 0; }
P1039 偵探推理