您的位置:首页 > 其它

【USACO题库】2.4.1 The Tamworth Two两只塔姆沃斯牛

2016-04-07 21:34 411 查看

题目描述

两只牛在森林里故意走丢了。农民John开始用他的专家技术追捕这两头牛。你的任务是模拟他们的行为(牛和John)。追击在10x10的平面网格内进行。一个格子可以是:一个障碍物,两头牛(它们总在一起), 或者农民John.

两头牛和农民John可以在同一个格子内(当他们相遇时),但是他们都不能进入有障碍的格子。

一个格子可以是:

. 空地

* 障碍物

C 两头牛

F 农民John

*...*.....
......*...
...*...*..
..........
...*.F....
*.....*...
...*......
..C......*
...*.*....
.*.*......


牛在地图里以固定的方式游荡。每分钟,它们可以向前移动或是转弯。如果前方无障碍且不会离开地图,它们会按照原来的方向前进一步。否则它们会用这一分钟顺时针转90度。
农民John, 深知牛的移动方法,他也这么移动。

每次(每分钟)农民John和两头牛的移动是同时的。如果他们在移动的时候穿过对方,但是没有在同一格相遇,我们不认为他们相遇了。当他们在某分钟末在某格子相遇,那么追捕结束。开始时,John和牛都面向北方。

INPUT FORMAT

Lines 1-10:

每行10个字符,表示如上文描述的地图。

SAMPLE INPUT (file ttwo.in)

*...*.....
......*...

...*...*..
..........

...*.F....

*.....*...

...*......

..C......*

...*.*....

.*.*......

OUTPUT FORMAT

输出一个数字,表示John需要多少时间才能抓住牛们。输出0,如果John无法抓住牛。

SAMPLE OUTPUT (file ttwo.out)

49

这道题目其实非常简单,只要模拟即可,唯一的难点在于如何碰到John——me无法抓到牛的情况。当总搜索量大于(10²*4)²的时候两人还没相遇——break,输出0(因为10²是棋盘大小,乘4是因为四个方向,然后有两个人,所以还要再加个平方)
代码:

var
bz:array[0..11,0..11] of Boolean;
x1,y1,x2,y2,i,j,fx,fy,tot1,tot2,ans:Longint;
ch:char;

Procedure init;
begin
fillchar(bz,sizeof(bz),true);

for i:=1 to 10 do
begin
for j:=1 to 10 do
begin
read(ch);
if ch='C' then
begin
x1:=i;
y1:=j;
end;
if ch='F' then
begin
x2:=i;
y2:=j;
end;
if ch='*' then bz[i,j]:=false;
end;
readln;
end;

for i:=1 to 10 do
begin
bz[0,i]:=false;
bz[i,0]:=false;
bz[11,i]:=false;
bz[i,11]:=false;
end;

bz[0,0]:=false;
bz[11,0]:=false;
bz[0,11]:=false;
end;

Procedure work;
begin
fx:=1;
fy:=1;

while true do
begin
inc(ans);
case fx of
1:if not bz[x1-1,y1] then inc(fx) else dec(x1);
2:if not bz[x1,y1+1] then inc(fx) else inc(y1);
3:if not bz[x1+1,y1] then inc(fx) else inc(x1);
4:if not bz[x1,y1-1] then inc(fx) else dec(y1);
end;

case fy of
1:if not bz[x2-1,y2] then inc(fy) else dec(x2);
2:if not bz[x2,y2+1] then inc(fy) else inc(y2);
3:if not bz[x2+1,y2] then inc(fy) else inc(x2);
4:if not bz[x2,y2-1] then inc(fy) else dec(y2);
end;

if fx<>4 then fx:=fx mod 4;
if fy<>4 then fy:=fy mod 4;

if (x1=x2) and (y1=y2) then
begin
writeln(ans);
exit;
end;

if ans>160000 then
begin
writeln(0);
exit;
end;
end;
end;

begin
init;

work;
end.


但是其实可以不用这样子判断,可以加一个六维数组,判断当前第一个人坐标,以及第二个人坐标,还有两个人的方向,如果这个状态被遇到两次则可以break(真不明白为什么上面6ms,加了这个反而0ms...)
var
f:array[1..10,1..10,1..10,1..10,1..4,1..4] of Boolean;
bz:array[0..11,0..11] of Boolean;
x1,y1,x2,y2,p1,q1,p2,q2,i,j,fx,fy,ans:Longint;
ch:char;
begin
fillchar(bz,sizeof(bz),true);
for i:=1 to 10 do
begin
for j:=1 to 10 do
begin
read(ch);
if ch='C' then
begin
x1:=i;
y1:=j;
end;
if ch='F' then
begin
x2:=i;
y2:=j;
end;
if ch='*' then bz[i,j]:=false;
end;
readln;
end;

fx:=1;
fy:=1;
p1:=x1;
q1:=y1;
p2:=x2;
q2:=y2;

while true do
begin
inc(ans);
x1:=p1; q1:=y1; x2:=p2; y2:=q2;
case fx of
1:if bz[x1-1,y1] and (x1>1)  then dec(x1) else inc(fx);
2:if bz[x1,y1+1] and (y1<10) then inc(y1) else inc(fx);
3:if bz[x1+1,y1] and (x1<10) then inc(x1) else inc(fx);
4:if bz[x1,y1-1] and (y1>1)  then dec(y1) else inc(fx);
end;

case fy of
1:if bz[x2-1,y2] and (x2>1)  then dec(x2) else inc(fy);
2:if bz[x2,y2+1] and (y2<10) then inc(y2) else inc(fy);
3:if bz[x2+1,y2] and (x2<10) then inc(x2) else inc(fy);
4:if bz[x2,y2-1] and (y2>1)  then dec(y2) else inc(fy);
end;

if fx<>4 then fx:=fx mod 4;
if fy<>4 then fy:=fy mod 4;

if (x1=x2) and (y1=y2) then
begin
writeln(ans);
exit;
end;

if f[x1,y1,x2,y2,fx,fy]=false then
begin
f[x1,y1,x2,y2,fx,fy]:=true;
p1:=x1; q1:=y1; p2:=x2; q2:=y2;
end
else
begin
writeln(0);
halt;
end;
end;
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: