魔鬼之城
源程序名 pils.???(pas, c, cpp) 可执行文件名 pils.exe 输入文件名 pils.in 输出文件名 pils.out |
【问题描述】
在一个被分割为N*M个正方形房间的矩形魔鬼之城中,一个探险者必须遵循下列规则才能跳跃行动。他必须从(1, 1)进入,从(N, M)走出;在每一房间的墙壁上都写了一个魔法数字,是1~13之内的自然数;探险者可以想像出8个方向中的任何一个(水平或垂直或对角线方向),随后他就可以作一次空间跳跃穿过这一方向上的连续的X个房间,其中X是他原来所在房间的魔法数字。但如果在这一方向上的房间数小于X,则他不作任何跳跃,而必须想像另一个方向。同时,探险者不能作连续两次相同方向的跳跃。
|
1 |
2 |
3 |
4 |
5 |
1 |
3 |
3 |
6 |
7 |
11 |
2 |
3 |
2 |
1 |
1 |
3 |
3 |
3 |
2 |
2 |
1 |
1 |
4 |
2 |
1 |
2 |
2 |
1 |
例如在上图的5*4的魔鬼之城中,如果探险者现在所在的位置是(3, 3),那么通过依次空间跳跃他可以到达下列房间中的一个:(1, 1),(3, 1),(1, 3),(5, 1),或(5, 3)。另外,如果他要用两次跳跃从(5, 4)到达(3, 2),则他不能首先跳到(4, 3)(因为这样他第二次跳跃的方向将和第一次相同,而这是不允许的)。所以他必须先跳跃到(2, 1)。
请你写一个程序,对给定的地图,算出探险者至少需要跳跃多少步才能离开魔鬼之城。
【输入】
一行给出N,M(都不超过100);
下来有M行,每行为N个自然数,表示对应房间中的魔法数字。
【输出】
出最小步数,如果探险者无法离开魔鬼之城,请输出“NEVER”。
【样例】
pils.in pils.out
5 4 4
3 3 6 7 11
3 2 1 1 3
3 2 2 1 1
2 1 2 2 1
======================
应该算是一个裸宽搜的题目吧。
应该注意的是到达一个点的8个状态是不相同的,如果只定义一个hash判断的话,算法就相当于变成了贪心(不过可以过9个点)。
还有一个需要注意的内容,对于一个棋盘类跳棋的问题来说,我们还可以定义一个常值数组来判断下一步的路线,这样可以有效的减少代码量,与增加代码可读性。
======================
type
re=record
x,y,step,last:longint;
end;
const
dx:array[1..8]of longint=(-1,-1,-1,1, 1,1,0, 0);
dy:array[1..8]of longint=(-1, 1, 0,1,-1,0,1,-1);
var
n,m:longint;
way:array[1..100,1..100]of longint;
f:array[-13..114,-13..114,1..8]of boolean;
h:array[0..200000]of re;
procedure init;
begin
assign(input,'pils.in');
assign(output,'pils.out');
reset(input); rewrite(output);
end;
procedure terminate;
begin
close(input); close(output);
halt;
end;
procedure bfs;
var
l,r:longint;
x_,y_:longint;
i:longint;
begin
l:=0; r:=1;
for i:=1 to 8 do
f[1,1,i]:=false;
h[1].x:=1; h[1].y:=1; h[1].step:=0; h[1].last:=0;
repeat
inc(l);
l:=l mod 200000;
for i:=1 to 8 do
if i<>h[l].last then
begin
x_:=h[l].x+dx[i]*way[h[l].x,h[l].y];
y_:=h[l].y+dy[i]*way[h[l].x,h[l].y];
if f[x_,y_,i] then
begin
f[x_,y_,i]:=false;
inc(r);
r:=r mod 200000;
h[r].x:=x_;
h[r].y:=y_;
h[r].step:=h[l].step+1;
h[r].last:=i;
if (x_=m)and(y_=n) then
begin
writeln(h[r].step);
terminate;
end;
end;
end;
until l>=r;
end;
procedure main;
var
i,j,K:longint;
begin
readln(n,m);
fillchar(f,sizeof(f),false);
for i:=1 to m do
for j:=1 to n do
begin
read(way[i,j]);
for k:=1 to 8 do
f[i,j,k]:=true;
end;
bfs;
writeln('NEVER');
end;
begin
init;
main;
terminate;
end.