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

题目描述

两只牛在森林里故意走丢了。农民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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值