Noip 2003T2 侦探推理

18 篇文章 0 订阅
14 篇文章 0 订阅

题目:

 侦探推理

来源:

 Noip 2003T2

题目大意:

 M个人参加游戏,每人提供一句或多句证言,共P句证言。其中N个人始终说假话,  其余的人始终说真话。请你通过证言判断出谁是罪犯。
    证言形式如下:
 证词内容  证词含义
 I am guilty. 我是罪犯
 I am not guilty. 我不是罪犯  
 XXX is guilty. XXX是罪犯(XXX表示某个同学的名字)
 XXX is not guilty. XXX不是罪犯
 Today is XXX.今天是XXX(XXX表示星期几,是Monday Tuesday Wednesday  Thursday Friday Saturday Sunday其中之一)
 证词中出现的其它话,都不列入逻辑推理的内容。

数据范围:

 M(1≤M≤20)、N(1≤N≤M)和P(1≤P≤100)

样例:

 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

做题思路:

 或者说是枚举或者说是dfs,最主要的是把句子转化成能用的信息,然后一个一个的  判断。

知识点:

 模拟、dfs

const
 w:array[1..7] ofstring=('Monday','Tuesday','Wednesday',
                     Thursday','Friday','Saturday','Sunday');
type
 re=record
 x,y,next:longint;
 end;
var
 nam:array[0..21] of string;
 a:array[0..101] of re;
 f,c:array[0..21] of longint;
 d:array[0..21] of boolean;
 n,m,p:longint;
 tot:longint;
procedure chuli;
var
 s,s1,s2,s3:string;
 i:longint;
 xx:longint;
begin
 readln(s);
 s1:=copy(s,1,pos(': ',s)-1);{<说话人的名字>}
 s2:=copy(s,pos(': ',s)+2,length(s)-pos(':',s)+1); {<说的内容>}
 fori:=1 to n do
  ifnam[i]=s1 then{<先找到这个人,然后对其进行处理,指向他的下一个>}
  begin
   xx:=i;
   inc(tot);
    a[tot].next:=f[xx];
   f[xx]:=tot;
   break;
   end;
 a[tot].x:=0; a[tot].y:=0;
 ifs2='I am guilty.' then
  begin
  a[tot].x:=xx;
  a[tot].y:=2; {<说是的标2>}
  exit;
  end;
 ifs2='I am not guilty.' then
  begin
  a[tot].x:=xx;
  a[tot].y:=1; {<说不是的1>}
  exit;
  end;
 ifcopy(s2,length(s2)-9,10)='is guilty.' then
  begin
  s3:=copy(s2,1,length(s2)-11);
   fori:=1 to n do
    ifnam[i]=s3 then
    begin
     a[tot].x:=i;
     a[tot].y:=2;
     break;
    end;
  exit;
  end;
 ifcopy(s2,length(s2)-13,14)='is not guilty.' then
  begin
  s3:=copy(s2,1,length(s2)-15);
   fori:=1 to n do
    ifnam[i]=s3 then
    begin
     a[tot].x:=i;
     a[tot].y:=1;
     break;
    end;
  exit;
  end;
 ifcopy(s2,1,8)='Today is' then
  begin
  s3:=copy(s2,10,length(s2)-10);
   fori:=1 to 7 do
    ifs3=w[i] then
    begin
     a[tot].x:=i;
     a[tot].y:=3; {<星期标3>}
    end;
  end;
 if(a[tot].x=0)and(a[tot].y=0) then{<是废话的删掉前面做的处理>}
  begin
  f[xx]:=a[tot].next;
  a[tot].next:=0;
  dec(tot);
  end;
end;
procedure work; {<判断是否有冲突,如果没有的话执行到最后处理输出>}
var
 i,t:longint;
 b:array[0..20] of 0..2;
 w:array[0..7] of 0..2;
 week:integer;
 sum:longint;
 na:string;
begin
 fillchar(b,sizeof(b),0);
 fillchar(w,sizeof(w),0);
 week:=0;
 fori:=1 to n do
  ifnot d[i] then
  begin
   t:=f[i];
   while t<>0 do
    begin
     if a[t].y=3 then
      begin
       if w[a[t].x]=1 then exit else w[a[t].x]:=2;
      end
     else
      begin
       if b[a[t].x]<>a[t].y  then
        begin
         if a[t].y=1 then b[a[t].x]:=2 else b[a[t].x]:=1;
        end
       else exit;
      end;
     t:=a[t].next;
    end;
   end
  else
  begin
   t:=f[i];
   while t<>0 do
    begin
     if a[t].y=3 then
      begin
       if (w[a[t].x]=2)or((w[a[t].x]=0)and(week>1)) then exit else
        begin
         w[a[t].x]:=1;
         inc(week);
        end;
      end
     else
      begin
       if (b[a[t].x]=0)or(b[a[t].x]=a[t].y) then
        begin
         b[a[t].x]:=a[t].y;
        end
       else exit;
      end;
     t:=a[t].next;
    end;
   end;
 sum:=0;
 fori:=1 to n do
  ifb[i]=2 then
  begin
   inc(sum);
   na:=nam[i];
   end;
 ifsum=0 then
  fori:=1 to n do
   ifb[i]=0 then
   begin
    inc(sum);
    na:=nam[i];
   end;
 ifsum>1 then
  begin
  writeln('Cannot Determine');
  close(input);
  close(output);
  halt;
  end;
 ifsum=1 then
  begin
  writeln(na);
  close(input);
  close(output);
  halt;
  end;
 ifsum=0 then
  begin
  writeln('Impossible');
  close(input);
  close(output);
  halt;
  end;
end;
procedure dfs(k,h:longint); {<枚举说谎的>}
var
 i:longint;
begin
 ifh>m then begin work;exit; end;
 fori:=k+1 to n-m+h do
  begin
  d[i]:=false;
  dfs(i,h+1);
  d[i]:=true;
  end;
end;
procedure init;
var
 i,j:longint;
begin
 readln(n,m,p);
 fillchar(d,sizeof(d),true);
 fori:=1 to n do readln(nam[i]);
 fori:=1 to p do chuli;
 dfs(0,1);
 writeln('Impossible');
end;
begin
assign(input,'logic.in');
assign(output,'logic.out');
reset(input);
rewrite(output);
 init;
close(input);close(output);
end.
题目来源: http://yt.tyvj.cn:8080/Problem_Show.asp?id=1039

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值