海盗船(corsair)
【问题描述】
有一个很有趣的游戏叫做海盗船。这是一个在9*8的棋盘上进行的游戏,棋盘上的每个格子可能是下面4种状态之一:
“.”:表示当前格子为空;
“S”:表示你的船所在的位置;
“E”:表示敌船所在的位置;
“#”:表示一座小岛。
每次你可以将你的船朝周围的8个方向之一移动,但不能停留。在你移动完之后,所有的敌船会朝周围8个位置中和你的船当前位置距离最近的那个格子移动。在这个过程中,如果某艘敌船碰到了小岛,那么这艘敌船将会沉没。如果两艘敌船同时走到同一个格子中,那么这两艘敌船将会同时沉没,并且其残骸将会在该位置形成障碍,也就是说如果还有敌船走到这个位置,那么该敌船也会沉没。每艘敌船上都装了烈性炸药,如果你不幸让某艘敌船撞到了你,你就可以和我们敬仰的祖先欢聚一堂了。
现在你的任务是通过移动你的船来消灭所有的敌船,当然,在移动过程中,请确保你的船不要撞倒小岛或者敌船的残骸。
【输入格式】
输入文件第一行包含一个整数T,表示测试数据组数,以下每组数据包含一个9*8的地图,地图上的符号以及意义如题目所述。相邻的两组数据间用一个空行隔开。
【输出格式】
输出文件对于每组数据输出一行信息。如果你能够消灭所有的海盗船,那么输出“I'm the king of the Seven Seas!”,否则输出“Oh no! I'm a dead man!”。
【输入样例】
2
........
........
........
...E....
...#S...
........
........
........
.......E
........
........
.....E..
..E#.#..
....S...
...#.#E.
...E....
........
........
【输出样例】
I'm the king ofthe Seven Seas!
Oh no! I'm adead man!
分析:
本题考查搜索,深搜广搜都可以,但对于本题广搜时间效率高一些,而且本题练习广搜还是很好地,所以我选择了广搜。
读题后可以发现这个地图上一个格子可能存在5种状态:“你”的船,敌船,小岛,敌船相撞的残骸和空,出于方便我们可以把敌船,小岛,残骸都归为敌船,但真正的敌船会动,用一个布尔数组标为 TRUE,小岛和残骸不能动,标为FALSE。只要你的船碰到这些东西都会挂掉。
对于不动的敌船(小岛,残骸)我们不必考虑,对于可以移动的敌船我们只要根据其坐标与你的船的坐标的关系即可得出其移动方向:位于你的船左上的船将向右下移动,位于上方的船将向下移动......。
处理了这些大概程序也不难写出了,将你的船坐标放入队列中,对于队首元素枚举与其相邻的八个点,如果该点没有敌船,且你的船在该点不会被迎面而来的敌船撞死,则记录状态,入队。如果能够消灭敌船则结束。
程序(好吧写的很乱):
program corsair;
var
px:array[1..8]of longint=(0,0,1,1,1,-1,-1,-1);
py:array[1..8]of longint=(1,-1,0,1,-1,1,0,-1);
dx,dy:array[0..200000]of longint;
r:array[0..200000,1..72,1..2]of longint;
v:array[0..200000,1..72]of boolean;
n,nx:longint;
i,m,j,l,h,t,x,y,xx,yy,g,k,u:longint;
c:char;
s:string;
function ffa(x,y:longint):boolean;//由于是你的船先走,所以要判断出会不会自己撞到敌船
var i:longint;
begin
ffa:=true;
for i:=1 to m do
if (r[h,i,1]=x)and(r[h,i,2]=y) then begin ffa:=false; break; end;
end;
procedure ppa;//处理敌船的移动,判断敌船是否撞到你,并且要判断出哪些敌船同其他敌船相撞或撞到小岛,若撞到,则两者都标为false
var i,j,x,y:longint;
begin g:=0;
for i:=1 to m do
if v[t,i]=true then
begin
x:=r[h,i,1]; y:=r[h,i,2];
if (x<dx[t])and(y<dy[t]) then begin r[t,i,1]:=x+1; r[t,i,2]:=y+1; end;
if (x>dx[t])and(y<dy[t]) then begin r[t,i,1]:=x-1; r[t,i,2]:=y+1;end;
if (x<dx[t])and(y>dy[t]) then begin r[t,i,1]:=x+1; r[t,i,2]:=y-1; end;
if (x>dx[t])and(y>dy[t]) then begin r[t,i,1]:=x-1; r[t,i,2]:=y-1;end;
if (x=dx[t])and(y<dy[t]) then begin r[t,i,1]:=x; r[t,i,2]:=y+1; end;
if (x=dx[t])and(y>dy[t]) then begin r[t,i,1]:=x; r[t,i,2]:=y-1;end;
if (x>dx[t])and(y=dy[t]) then begin r[t,i,1]:=x-1; r[t,i,2]:=y; end;
if (x<dx[t])and(y=dy[t]) then begin r[t,i,1]:=x+1; r[t,i,2]:=y;end;
if (r[t,i,1]=dx[t])and(r[t,i,2]=dy[t]) then begin g:=1; break;end;
end;
if g=0 then begin
g:=2;
for i:=1 to m-1 do
for j:=i+1 to m do
if (r[t,i,1]=r[t,j,1])and(r[t,i,2]=r[t,j,2]) then
begin v[t,i]:=false; v[t,j]:=false; end;
for i:=1 to m do
if v[t,i]=true then g:=0; end;
end;
begin
assign(input,'corsair.in');
reset(input);
assign(output,'corsair.out');
rewrite(output);
readln(n);
for l:=1 to n do
begin m:=0; k:=0;
for i:=1 to 9 do begin readln(s);
for j:=1 to 8 do
begin c:=s[j]; if c='S' then begin x:=i; y:=j; end;
if c='E' then begin m:=m+1; r[1,m,1]:=i; r[1,m,2]:=j; v[1,m]:=true;end;
if c='#' then begin m:=m+1; r[1,m,1]:=i; r[1,m,2]:=j; v[1,m]:=false;end;
end;
end; u:=m;
h:=0; t:=1; dx[1]:=x; dy[1]:=y;
while h<t do
begin
h:=h+1;
for i:=1 to 8 do
begin
xx:=dx[h]+px[i]; yy:=dy[h]+py[i]; m:=u;
if (xx>0)and(xx<=9)and(yy>0)and(yy<=8)and(ffa(xx,yy)=true) then
begin
t:=t+1; dx[t]:=xx; dy[t]:=yy; r[t]:=r[h]; v[t]:=v[h]; g:=0; m:=u;//不知为何m在循环几次后变为0,只好中途在重新赋值
ppa; if g=1 then t:=t-1 else if g=2 then
begin
writeln('I''','m the king of the Seven Seas!');
k:=1; break;
end;
end;
end;
if k=1 then break; if t>199000 then break;//防止超出数组边界
end; n:=nx; readln;//每组数据注意要换行
if k=0 then writeln('Oh no! I''','m a dead man!');//注意要输出单引号,再加一个单引号
end;
close(input); close(output);
end.