回溯算法_迷宫问题
AYYZOJ p1418
COGS p1105
【问题描述】
有一个m*n格的迷宫(表示有m行、n列),其中有可走的也有不可走的,如果用1表示可以走,0表示不可以走,文件读入这m*n个数据和起始点、结束点(起始点和结束点都是用两个数据来描述的,分别表示这个点的行号和列号)。现在要你编程找出所有可行的道路,要求所走的路中没有重复的点,走时只能是上下左右四个方向。如果一条路都不可行,则输出相应信息(用-l表示无路)。
【输入】
第一行是两个数m,n(1<m,n<15),接下来是m行n列由1和0组成的数据,最后两行是起始点和结束点。
【输出】
所有可行的路径,描述一个点时用(x,y)的形式,除开始点外,其他的都要用“->”表示方向。
如果没有一条可行的路则输出-1。
【样例】
maze.in
5 6
1 0 0 1 0 1
1 1 1 1 1 1
0 0 1 1 1 0
1 1 1 1 1 0
1 1 1 0 1 1
1 1
5 6
maze.out
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(2,5)->(3,5)->(3,4)->(3,3)->(4,3)->(4,4)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(2,5)->(3,5)->(3,4)->(4,4)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(2,5)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(3,4)->(3,3)->(4,3)->(4,4)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(3,4)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(3,4)->(4,4)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(3,4)->(2,4)->(2,5)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(3,4)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(3,4)->(4,4)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(4,3)->(4,4)->(3,4)->(2,4)->(2,5)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(4,3)->(4,4)->(3,4)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(4,3)->(4,4)->(4,5)->(5,5)->(5,6)
【样例解释】:由于搜索时试探的顺序不一样,路线方案也就不同,输出样例中试探方向是按左、上、右、下的顺序试探的,编程时请按此顺序试探,否则可能结果与标准数据输出不一致。
【算法分析】
用一个a数组来存放迷宫可走的情况,另外用一个数组b来存放哪些点走过了。每个点用两个数字来描述,一个表示行号,另一个表示列号。对于某一个点(x,y),四个可能走的方向的点描述如下表:
|
|
1 |
|
|
4 |
x,y |
2 |
|
|
3 |
|
对应的位置为:(x-1, y),(x, y+1),(x+1, y),(x, y-1)。所以每个点都要试探四个方向,如果没有走过(数组b相应的点的值为0)且可以走(数组a相应点的值为1)同时不越界,就走过去,再看有没有到达终点,到了终点则输出所走的路,否则继续走下去。
注意:参考程序中的遍历顺序是左上右下,cogs中遍历顺序是上左右下。
1 const 2 x1:array[1..4] of integer=(0,-1,0,1); 3 y1:array[1..4] of integer=(-1,0,1,0); 4 maxnm=15; 5 var 6 n,m,x,y,i,j,maxm,maxn,xx,yy: byte; 7 g,b:array[0..maxnm,0..maxnm] of 0..1; 8 t:array[1..maxnm*maxnm,1..2] of integer; 9 total:longint; 10 procedure print; 11 var i:integer; 12 begin 13 write('(',t[1,1],',',t[1,2],')'); 14 for i:=2 to j do 15 write('->(':2,t[i,1],',',t[i,2],')'); 16 writeln; 17 end; 18 procedure sol(x,y:integer); 19 var i,xx,yy:integer; 20 begin 21 for i:=1 to 4 do 22 begin 23 if (x+x1[i]>=1) and (x+x1[i]<=maxm) and (y+y1[i]>=1) and (y+y1[i]<=maxn) and (g[x+x1[i],y+y1[i]]=1) and (b[x+x1[i],y+y1[i]]=0) then 24 begin 25 xx:=x+x1[i];yy:=y+y1[i]; 26 inc(j); 27 t[j,1]:=xx; t[j,2]:=yy; 28 b[xx,yy]:=1; 29 if (xx=m) and (yy=n) then begin inc(total); print;end 30 else sol(xx,yy); 31 b[xx,yy]:=0; 32 dec(j); 33 end; 34 end; 35 end; 36 begin 37 readln(maxm,maxn); 38 for i:=1 to maxm do 39 begin 40 for j:=1 to maxn do 41 read(g[i,j]); 42 readln; 43 end; 44 readln(x,y); 45 readln(m,n); 46 total:=0;j:=1;t[1,1]:=x;t[1,2]:=y; 47 b[x,y]:=1; 48 sol(x,y); 49 if total=0 then writeln('-1'); 50 end.