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.

 

posted @ 2017-03-01 21:05  bobble  阅读(329)  评论(0编辑  收藏  举报