[NOIP2003提高组]侦探推理
Posted Mrsrz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[NOIP2003提高组]侦探推理相关的知识,希望对你有一定的参考价值。
题目:洛谷P1039、Vijos P1106、codevs1089。
题目大意:给你一系列证词,要你求出谁是凶手。具体题目见原题。
解题思路:我们枚举犯人和星期,一个一个进行判断。如果成功则记录答案,如果成功且以前已经记录了答案,则说明有多个凶手,输出“Cannot Determine”,如果最后没有答案,则输出“Impossible”。主要是字符串的处理。其他细节见代码注释。
然而我的初始代码用了getline,在Linux下最后会读入Windows的换行符!!这个问题我找了半天!!后来我把代码稍微改了一下(代码第85~87行的处理),使其兼容Linux和Windows(洛谷和codevs是Linux的,Vijos是Windows的)。
C++ Code:
#include<iostream> #include<cstring> #include<string> #include<map> #include<cstdlib> using namespace std; const string days[]={ "Today is Monday.", "Today is Tuesday.", "Today is Wednesday.", "Today is Thursday.", "Today is Friday.", "Today is Saturday.", "Today is Sunday." }; map<string,int>num;//记录编号 string name[22];//名字 int n,m,p,cnt,ans,TF[102],T,F;//T表示当前说真话的人数,F表示当前说假话的人数,TF[i]表示i说真话还是假话 struct word{//id是说这句话的人的编号,st是说的话 int id; string st; }f[102]; string s; bool pdTF(int id,bool b){//判断是否有冲突,返回1表示有冲突 if(TF[id]==-1){ TF[id]=b; if(b)++T;else ++F; }else{ if(TF[id]==b)return 0;else return 1; } if(F>m||T>n-m)return 1; return 0; } void Judge(int Xs,string day){//测试,若有冲突则直接跳出来 memset(TF,-1,sizeof(TF)); T=F=0; for(int i=1;i<=p;++i){ int pos; pos=f[i].st.find("I am guilty."); if(~pos){ if(pdTF(f[i].id,f[i].id==Xs))return; } pos=f[i].st.find("I am not guilty."); if(~pos){ if(pdTF(f[i].id,f[i].id!=Xs))return; } pos=f[i].st.find(" is guilty."); if(~pos){ string now=f[i].st; now.erase(pos,11); int id=num[now]; if(pdTF(f[i].id,id==Xs))return; } pos=f[i].st.find(" is not guilty."); if(~pos){ string now=f[i].st; now.erase(pos,15); int id=num[now]; if(pdTF(f[i].id,id!=Xs))return; } pos=f[i].st.find("Today is "); if(~pos){ if(pdTF(f[i].id,f[i].st==day))return; } } /*全部语句检测完毕,没有冲突*/ if(ans&&ans!=Xs){//已有答案但不是当前凶手,说明有多个凶手 cout<<"Cannot Determine"<<endl; exit(0);//直接结束程序 } ans=Xs; } int main(){ cin>>n>>m>>p; for(int i=1;i<=n;++i){ cin>>name[i]; num[name[i]]=i; } for(int i=1;i<=p;++i){ cin>>s; s.erase(s.length()-1,1); f[i].id=num[s]; getline(cin,f[i].st); f[i].st.erase(0,1); char ch=f[i].st[f[i].st.length()-1]; if(ch==‘\n‘||ch==‘\r‘||ch==‘ ‘) f[i].st.erase(f[i].st.length()-1,1); } ans=0; for(int i=1;i<=n;++i) for(int j=0;j<7;++j) Judge(i,days[j]); if(!ans)//没有搜到凶手 cout<<"Impossible"<<endl;else cout<<name[ans]<<endl; return 0; }
以上是关于[NOIP2003提高组]侦探推理的主要内容,如果未能解决你的问题,请参考以下文章