题目: | 侦探推理 | |
来源: | Noip 2003T2 | |
题目大意: | M个人参加游戏,每人提供一句或多句证言,共P句证言。其中N个人始终说假话, 其余的人始终说真话。请你通过证言判断出谁是罪犯。 | |
数据范围: | 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