LUOGU P1039 偵探推理 (字串+模擬)
阿新 • • 發佈:2018-11-06
解題思路
一道%你神題,\(string\)好強大啊。。首先列舉一個周幾,再列舉一個罪犯是誰,然後判斷的時候就是列舉所有人說的話。定義\(fAKe[i]\)表示第\(i\)個人說的是真話還是假話還是未知。然後如果遇到\(xx is guilty\)或\(I am guilty\)之類的話,就看列舉的罪犯是否為這個人。如果說的是\(Today is xxx\),就看當前列舉的星期是否為這一天。
程式碼
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<string> #include<map> using namespace std; const int MAXN = 25; int n,m,p,fAKe[MAXN],w[205],ans,now,err; string name[MAXN],say[205]; string day[10]={"","Today is Sunday.","Today is Monday.","Today is Tuesday.","Today is Wednesday." ,"Today is Thursday.","Today is Friday.","Today is Saturday."}; map<string,int> mp; void solve(int x,int y){ if(!fAKe[x]) fAKe[x]=y; else if(fAKe[x] && fAKe[x]!=y) err=1; } int main(){ scanf("%d%d%d",&m,&n,&p); for(int i=1;i<=m;i++) cin>>name[i],mp[name[i]]=i; for(int i=1;i<=p;i++){ string nm;cin>>nm; nm.erase(nm.end()-1);w[i]=mp[nm]; getline(cin,say[i]);say[i].erase(say[i].begin()); say[i].erase(say[i].end()-1); } for(int td=1;td<=7;td++) for(int chp=1;chp<=m;chp++){ //列舉罪犯 err=0;int who,cnt,pp; memset(fAKe,0,sizeof(fAKe)); for(int i=1;i<=p;i++){ who=w[i]; if(say[i]=="I am guilty.") solve(who,who==chp?1:-1); if(say[i]=="I am not guilty.") solve(who,who==chp?-1:1); for(int j=1;j<=7;j++) if(say[i]==day[j]) {solve(who,j==td?1:-1);break;} for(int j=1;j<=m;j++){ if(say[i]==name[j]+" is guilty.") solve(who,chp==j?1:-1); if(say[i]==name[j]+" is not guilty.") solve(who,chp==j?-1:1); } } cnt=pp=0; for(int i=1;i<=m;i++) { if(!fAKe[i]) pp++; if(fAKe[i]==-1) cnt++; } if(err || cnt>n || cnt+pp<n) continue; if(ans && ans!=chp) { puts("Cannot Determine"); return 0; } ans=chp; } if(ans) cout<<name[ans]; else puts("Impossible"); return 0; }