NOIP2003tg 侦探推理 极其码农的暴力
侦探推理
题目描述
明明同学最近迷上了侦探漫画《柯南》并沉醉于推理游戏之中,于是他召集了一群同学玩推理游戏。游戏的内容是这样的,明明的同学们先商量好由其中的一个人充当罪犯(在明明不知情的情况下),明明的任务就是找出这个罪犯。接着,明明逐个询问每一个同学,被询问者可能会说:
证词中出现的其他话,都不列入逻辑推理的内容。
明明所知道的是,他的同学中有N个人始终说假话,其余的人始终说真。
现在,明明需要你帮助他从他同学的话中推断出谁是真正的凶手,请记住,凶手只有一个!
输入输出格式
输入格式:输入由若干行组成,第一行有二个整数,M(1≤M≤20)、N(1≤N≤M)和P(1≤P≤100);M是参加游戏的明明的同学数,N是其中始终说谎的人数,P是证言的总数。接下来M行,
每行是明明的一个同学的名字(英文字母组成,没有主格,全部大写)。
往后有P行,每行开始是某个同学的名宇,紧跟着一个冒号和一个空格,后面是一句证词,符合前表中所列格式。证词每行不会超过250个字符。
输入中不会出现连续的两个空格,而且每行开头和结尾也没有空格。
输出格式:如果你的程序能确定谁是罪犯,则输出他的名字;如果程序判断出不止一个人可能是罪犯,则输出 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
思路呢?
我的思路比较复杂。。。
首先读入人名
读入说的话, 感觉似乎不用区分大小写,所以用了UPCASE
cutname找到sayer,用adder加入命令
将无聊的话排除,记录有用的话
. 用command[i].say表示说话的人,
. command[i].ter[0]表示说的话属于哪些类型,如下
. 1 我是罪犯
. 2 我不是罪犯
. 3 xxx是罪犯
. 4 xxx不是罪犯
. 5 今天星期几
. command[i].ter[j](0<j<=5) 表示说的对象
然后枚举犯人和星期几,构造情况,如果情况满足就给answer的种数加一,
. 不过要注意找到一个犯人时,就不用枚举后面的星期几,因为后面就算还有也是同一个犯人
在构造情况时如何判断是否满足呢?
. 如果说的是“我是”或者“xxx是”或者“今天是”就判断说的对象command[i].ter[j]如果和枚举的情况相反就撒谎人数加一
. 相反如果是“我不是”或者“xxx不是”就判断说的对象command[i].ter[j]如果和枚举的情况相同就撒谎人数加一
. 但是,如果以前处理过的语句中的sayer而且后面又讲了话,那么反过来处理,他现在的话的反话如果和枚举的情况冲突就退出
如何处理无聊的话?
. 我们在处理第i条语句时,可以顺便把第I条语句的说话人command[i].say的yo赋为true,表示这人说过有用的话
. 然后如果构造处理的情况说实话的人数【就是m-sum】 大与 题目要求说实话的人数【m-n】就把说无聊话的人判断为假话,使得满足题目情况
1 program logic; 2 const 3 inf='logic.in'; 4 outf='logic.out'; 5 day:array[1..7]of string=('MONDAY','TUESDAY','WEDNESDAY', 6 'THURSDAY','FRIDAY','SATURDAY','SUNDAY'); 7 type 8 node=record 9 say:longint; 10 ter:array[0..5] of longint; 11 end; 12 var 13 m,i,p,n,tot,totc,sayer,dayy,guilty,answer,j,toty:longint; 14 bobo:boolean; 15 name:array[1..100] of string; 16 command:array[1..100] of node; 17 yo:array[1..100] of boolean; 18 st,nono,crimin:string; 19 20 function findday(oppo:string):longint; 21 var 22 xh:longint; 23 begin 24 for xh:= 1 to 7 do 25 if day[xh]=oppo then exit(xh); 26 end; 27 28 function findpeople(oppo:string):longint; 29 var 30 xh:longint; 31 begin 32 for xh:= 1 to m do 33 if name[xh]=oppo then exit(xh); 34 end; 35 36 procedure cutname; 37 var 38 tmp:longint; 39 t:string; 40 begin 41 tmp:=pos(' ',st); 42 t:=copy(st,1,tmp-2); 43 sayer:=findpeople(t); 44 end; 45 46 procedure adder; 47 var 48 choose,start,cutlen:longint; 49 begin 50 51 if pos('I AM GUILTY',ST)<>0 then begin 52 inc(totc); 53 command[totc].say:=sayer; 54 command[totc].ter[1]:=sayer; 55 command[totc].ter[0]:=1; 56 exit; 57 end; 58 if pos('I AM NOT GUILTY',ST)<>0 then begin 59 inc(totc); 60 command[totc].say:=sayer; 61 command[totc].ter[2]:=sayer; 62 command[totc].ter[0]:=2; 63 exit; 64 end; 65 choose:=pos('IS GUILTY',ST); 66 if choose<>0 then begin 67 inc(totc); 68 command[totc].say:=sayer; 69 start:=pos(' ',st)+1; 70 cutlen:=choose-start-1; 71 nono:=copy(st,start,cutlen); 72 command[totc].ter[3]:=findpeople(nono); 73 command[totc].ter[0]:=3; 74 exit; 75 end; 76 choose:=pos('IS NOT GUILTY',ST); 77 if choose<>0 then begin 78 inc(totc); 79 command[totc].say:=sayer; 80 start:=pos(' ',st)+1; 81 cutlen:=choose-start-1; 82 nono:=copy(st,start,cutlen); 83 command[totc].ter[4]:=findpeople(nono); 84 command[totc].ter[0]:=4; 85 exit; 86 end; 87 choose:=pos('TODAY IS ',ST); 88 if choose<>0 then begin 89 inc(totc); 90 command[totc].say:=sayer; 91 start:=choose+9; 92 cutlen:=length(st)-start; 93 nono:=copy(st,start,cutlen); 94 command[totc].ter[5]:=findday(nono); 95 command[totc].ter[0]:=5; 96 bobo:=false; 97 exit; 98 end; 99 end; 100 101 procedure outgo; 102 begin 103 close(input); close(output); 104 halt; 105 end; 106 107 procedure bruteforce; 108 var 109 lie,oker:array[1..100] of boolean; 110 sum:longint; 111 begin 112 fillchar(lie,sizeof(lie),true); 113 fillchar(oker,sizeof(oker),true); 114 115 sum:=0; 116 for i:= 1 to totc do 117 if oker[i] then 118 begin 119 yo[command[i].say]:=true; 120 if lie[command[i].say] then 121 begin 122 123 if (command[i].ter[0]=1) or (command[i].ter[0]=3) then 124 begin 125 if command[i].ter[command[i].ter[0]]<>guilty then 126 if lie[command[i].say] then begin 127 inc(sum); 128 lie[command[i].say]:=false; 129 end; 130 continue 131 end; 132 if (command[i].ter[0]=2) or (command[i].ter[0]=4) then 133 begin 134 if command[i].ter[command[i].ter[0]]=guilty then 135 if lie[command[i].say] then begin 136 inc(sum); 137 lie[command[i].say]:=false; 138 end ; 139 140 continue 141 end; 142 if command[i].ter[command[i].ter[0]]<>dayy then 143 if lie[command[i].say] then begin 144 inc(sum); 145 lie[command[i].say]:=false; 146 end; 147 end 148 else 149 begin 150 if (command[i].ter[0]=1) or (command[i].ter[0]=3) then 151 if command[i].ter[command[i].ter[0]]=guilty then exit; 152 if (command[i].ter[0]=2) or (command[i].ter[0]=4) then 153 if command[i].ter[command[i].ter[0]]<>guilty then exit; 154 if command[i].ter[command[i].ter[0]]<>dayy then 155 if lie[command[i].say] then exit; 156 end; 157 end; 158 159 if m-n<m-sum then 160 for i:= 1 to m do 161 if yo[i]=false then begin inc(sum); if sum=n then break end; 162 if sum=n then begin inc(answer); crimin:=name[guilty]; end; 163 end; 164 165 begin 166 167 assign(input,inf); 168 assign(output,outf); 169 reset(input); 170 rewrite(output); 171 fillchar(yo,sizeof(yo),false); 172 173 readln(m,n,p); 174 for i:= 1 to m do 175 begin 176 inc(tot); 177 readln(name[tot]); 178 end; 179 bobo:=true; 180 181 for i:= 1 to p do 182 begin 183 readln(st); 184 st:=upcase(st); 185 cutname; 186 adder; 187 end; 188 189 for guilty:= 1 to m do 190 for dayy:= 1 to 7 do 191 begin 192 bruteforce; 193 if crimin=name[guilty] then break; 194 end; 195 196 if answer=1 then writeln(crimin) 197 else 198 if answer=0 then writeln('Impossible') 199 else if answer>=2 then writeln('Cannot Determine'); 200 201 outgo; 202 end.