【洛谷P1039】侦探推理
侦探推理
这是一道恶心至极的模拟题
我们可以枚举罪犯是谁,今天是星期几,从而判断每个人说的话是真是假
若每个人说的话的真假一致,且说谎话的人数<=k且说真话的人数<=m-k,就是一个符合的方案
而此题的精髓在于字符串的处理!
要知道每句话的末尾会有一个空格(为此爆到30分)
以及以下坑点:https://www.luogu.org/discuss/show/27320
CENGJINGYOUYIDUANZHENZHIDEGANQINGFANGZAIWOMIANQIANWOMEIYOUZHENXIDENGDAOSHIQULEYIHOUCAIZHUIHUIMOJIRENSHIJIANZUITONGKUDESHIMOGUOYUCIRUGUOSHANGTIANNENGGEIWOYIGEZAILAIYICIDEJIHUIWOHUIDUINAGENVHAIZISHUOSANGEZI:NIMABI !!!
具体看代码吧
#include<iostream> #include<cstring> #include<cstdio> #include<map> using namespace std; #define N 25 int n,m,p,cnt,ans; map<string,int> M; struct ZC{ int pos,type,to; //type 0:罪犯 1:不是罪犯 2:to是罪犯 3:to不是罪犯 4:today是to } a[N]; string s[N],s1,s2,s3,s4,d1,d2,d3,d4,d5,d6,d7; int h[N]; int main() { s1=" I am guilty."; s2=" I am not guilty."; s3=" is guilty."; s4=" is not guilty."; d1=" Today is Monday."; d2=" Today is Tuesday."; d3=" Today is Wednesday."; d4=" Today is Thursday."; d5=" Today is Friday."; d5=" Today is Saturday."; d7=" Today is Sunday."; string x; scanf("%d%d%d",&m,&n,&p); getline(cin,x); for(int i=1;i<=m;i++){ cin>>s[i]; M[s[i]]=i; } while(p--){ cin>>x; x.erase(x.end()-1); if(!M[x]){ getline(cin,x); continue; } a[++cnt].pos=M[x]; getline(cin,x); int it=x.find('.',0); x.erase(it+1,x.length()-1); if(x==s1) a[cnt].type=0; else if(x==s2){ a[cnt].type=1; } else if(x==d1){ a[cnt].type=4; a[cnt].to=1; } else if(x==d2){ a[cnt].type=4; a[cnt].to=2; } else if(x==d3){ a[cnt].type=4; a[cnt].to=3; } else if(x==d4){ a[cnt].type=4; a[cnt].to=4; } else if(x==d5){ a[cnt].type=4; a[cnt].to=5; } else if(x==d6){ a[cnt].type=4; a[cnt].to=6; } else if(x==d7){ a[cnt].type=4; a[cnt].to=7; } else{ x.erase(0,1); int it=x.find(' ',0); string y=x.substr(0,it); x.erase(0,it); if(!M[y]){ cnt--; continue; } a[cnt].to=M[y]; if(x==s3) a[cnt].type=2; else if(x==s4) a[cnt].type=3; else cnt--; } } for(int gu=1;gu<=m;gu++){ bool Flag=0; for(int day=1;day<=7;day++){ memset(h,0,sizeof(h)); bool flag=1; int tot1=0,tot2=0; for(int i=1;i<=cnt;i++){ int k; switch(a[i].type){ case 0:{ if(a[i].pos==gu) k=1; else k=2; break; } case 1:{ if(a[i].pos!=gu) k=1; else k=2; break; } case 2:{ if(a[i].to==gu) k=1; else k=2; break; } case 3:{ if(a[i].to!=gu) k=1; else k=2; break; } case 4:{ if(a[i].to==day) k=1; else k=2; break; } } if(!h[a[i].pos]) h[a[i].pos]=k; else if(h[a[i].pos]!=k) flag=0; if(!flag) break; } if(!flag) continue; for(int i=1;i<=m;i++) if(h[i]==1) tot1++; else if(h[i]==2) tot2++; if(tot2<=n&&n<=m-tot1){ Flag=1; break; } } if(Flag){ if(ans){ puts("Cannot Determine"); return 0; } else ans=gu; } } if(ans) cout<<s[ans]<<endl; else puts("Impossible"); return 0; } /*
附几个样例
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?? 2 2 4 HELLO GUILTY HELLO: What is your name? GUILTY: I am GUILTY. GUILTY: Are you guilty? HELLO: I am not guilty. 5 1 5 A B C D E A: Today is Monday. B: Today is Thursday. C: Today is Monday. B: D is not guilty. E: I am not guilty. */