[NOIP2003] 提高组 洛谷P1039 侦探推理
题目描述
明明同学最近迷上了侦探漫画《柯南》并沉醉于推理游戏之中,于是他召集了一群同学玩推理游戏。游戏的内容是这样的,明明的同学们先商量好由其中的一个人充当罪犯(在明明不知情的情况下),明明的任务就是找出这个罪犯。接着,明明逐个询问每一个同学,被询问者可能会说:
证词中出现的其他话,都不列入逻辑推理的内容。
明明所知道的是,他的同学中有N个人始终说假话,其余的人始终说真。
现在,明明需要你帮助他从他同学的话中推断出谁是真正的凶手,请记住,凶手只有一个!
输入输出格式
输入格式:
输入由若干行组成,第一行有二个整数,M(1≤M≤20)、N(1≤N≤M)和P(1≤P≤100);M是参加游戏的明明的同学数,N是其中始终说谎的人数,P是证言的总数。接下来M行,
每行是明明的一个同学的名字(英文字母组成,没有主格,全部大写)。
往后有P行,每行开始是某个同学的名宇,紧跟着一个冒号和一个空格,后面是一句证词,符合前表中所列格式。证词每行不会超过250个字符。
输入中不会出现连续的两个空格,而且每行开头和结尾也没有空格。
输出格式:
如果你的程序能确定谁是罪犯,则输出他的名字;如果程序判断出不止一个人可能是罪犯,则输出 Cannot Determine;如果程序判断出没有人可能成为罪犯,则输出 Impossible。
输入输出样例
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??
MIKE
惊天大模拟
惊天码农题
首先需要花式截取出每个人的信息,然后需要记录以下信息:
每个人说的日期
每个人说自己是不是罪犯
每个人说谁是罪犯
每个人说谁不是罪犯
枚举日期和嫌疑犯,进行判断:
记说谎人数为tmp,可疑人数为cnt(可疑人数指没有说过真话,也没有说过假话的人数),题目限制说谎人数为m
若tmp>m,说明当前枚举的情况不成立。
若tmp+cnt<m,说明已知说谎的人和可能说谎的人加起来都不够目标值,不成立。
除此之外的情况下,当前枚举到的嫌疑犯可能是罪犯。
若可能是罪犯的人数大于1人,cannot determine
1 /*By SilverN*/ 2 #include<iostream> 3 #include<cstdio> 4 #include<algorithm> 5 #include<cstring> 6 #include<cmath> 7 #include<vector> 8 #include<map> 9 using namespace std; 10 string pp[5]={"am guilty","am not guilty","is guilty.","is not guilty."}; 11 string week[8]={" ","is Monday","is Tuesday","is Wednesday","is Thursday","is Friday","is Saturday","is Sunday"}; 12 // 13 int n,m,p; 14 // 15 string name[30]; 16 map<string,int>mp; 17 //人名 18 string s[30]; 19 struct person{ 20 bool is;//是否确定是罪犯 21 int wk;//每个人对天气的判断 22 int guil[30];//每个人对其他人身份的判断 23 vector<int>g_list,nog_list;//每个人指认的罪犯 24 }a[30]; 25 //身份信息 26 bool posi[30]; 27 int work(int day,int uso){ 28 int cnt=0,tmp=0;//不确定的人,确定的凶手 29 30 for(int i=1;i<=n;i++){ 31 bool f_true=0,f_false=0; 32 if(a[i].is || (a[i].wk && a[i].wk!=day)){//天气说错 33 f_false=1; 34 } 35 if(a[i].guil[uso]==-1){//说罪犯不是罪犯 36 f_false=1; 37 } 38 if(a[i].guil[uso]==1)f_true=1;//说罪犯是罪犯 39 if(i!=uso && a[i].guil[i]==1){//不是罪犯说自己是罪犯 40 f_false=1; 41 } 42 for(int j=0;j<a[i].g_list.size();j++)if(a[i].g_list[j]!=uso){//说不是罪犯的人是罪犯 43 f_false=1; 44 } 45 for(int j=0;j<a[i].nog_list.size();j++)if(a[i].nog_list[j]!=uso){//说不是罪犯的人不是罪犯 46 f_true=1; 47 } 48 if(a[i].wk==day)f_true=1; 49 if(i==uso && a[i].guil[uso]==1) f_true=1;//凶手说自己是凶手 50 if(i!=uso && a[i].guil[i]==-1) f_true=1;//不是凶手说自己不是凶手 51 if(f_true && f_false)return 0;//不合法 52 if(f_false)tmp++; 53 if(!f_true && !f_false)cnt++;//不确定的人 54 } 55 // printf("day:%d uso:%d cnt:%d tmp:%d\n",day,uso,cnt,tmp); 56 57 if(tmp>m)return 0; 58 if(tmp+cnt<m)return 0; 59 return 1; 60 } 61 int target=0; 62 void solve(){ 63 int tmp=0; 64 int i,j; 65 for(i=1;i<=7;i++)//枚举日期 66 for(j=1;j<=n;j++)//枚举凶手 67 { 68 if(posi[j])continue; 69 if(work(i,j)){ 70 ++tmp; 71 posi[j]=1; 72 if(tmp>=2){ 73 printf("Cannot Determine\n"); 74 return; 75 } 76 target=j; 77 } 78 } 79 if(!target)printf("Impossible\n"); 80 cout<<name[target]<<endl; 81 return; 82 } 83 // 84 int main(){ 85 scanf("%d%d%d",&n,&m,&p);//总人数 说谎人数 证言数 86 int i,j; 87 for(i=1;i<=n;i++){ 88 cin>>name[i]; 89 mp[name[i]]=i; 90 } 91 for(i=1;i<=p;++i){ 92 cin>>s[i]; 93 // cout<<"test"<<s[i]<<endl; 94 s[i]=s[i].substr(0,s[i].find(':')); 95 // cout<<"finn"<<endl; 96 int id=mp[s[i]]; 97 getchar(); 98 getline(cin,s[i]); 99 // cout<<"now-"<<s[i]<<endl; 100 //判断 101 if(s[i][0]=='I'){ 102 if(s[i].find(pp[0])!=-1){//I am guilty 103 a[id].guil[id]=1; continue; 104 } 105 else if(s[i].find(pp[1])!=-1){//I am not guilty 106 a[id].guil[id]=-1; continue; 107 } 108 } 109 else{ 110 int tmp=0; 111 tmp=s[i].find(pp[2]); 112 if(tmp!=-1){//is guilty 113 // printf("is guilty: %d\n",tmp); 114 s[i]=s[i].substr(0,tmp-1); 115 // printf("mp:%d\n",mp[s[i]]); 116 // cout<<"test: "<<s[i]<<"eld"<<endl; 117 a[id].guil[mp[s[i]]]=1; 118 a[id].g_list.push_back(mp[s[i]]); 119 continue; 120 } 121 tmp=s[i].find(pp[3]); 122 if(tmp!=-1){//is not guilty 123 s[i]=s[i].substr(0,tmp-1); 124 // printf("mp:%d\n",mp[s[i]]); 125 // cout<<"test: "<<s[i]<<"eld"<<endl; 126 a[id].guil[mp[s[i]]]=-1; 127 a[id].nog_list.push_back(mp[s[i]]); 128 continue; 129 } 130 for(j=1;j<=7;j++)//天气判定 131 { 132 tmp=s[i].find(week[j]); 133 if(tmp!=-1){ 134 if(!a[id].wk) 135 a[id].wk=j; 136 else a[id].is=1;//天气前后矛盾,肯定是骗子 137 break; 138 } 139 } 140 } 141 // 142 } 143 //结束读入 144 /* 145 for(i=1;i<=n;i++){ 146 printf("info of %d:\n",i); 147 cout<<name[i]<<endl; 148 149 printf("wk: %d\n",a[i].wk); 150 printf("self: %d\n",a[i].guil[i]); 151 for(j=0;j<a[i].g_list.size();j++)printf("%d ",a[i].g_list[j]); 152 printf("\n"); 153 for(j=0;j<a[i].nog_list.size();j++)printf("%d ",a[i].nog_list[j]); 154 printf("\n"); 155 }*/ 156 // 157 solve(); 158 159 return 0; 160 }