遞迴入門 走迷宮

2021-09-28 18:08:49 字數 4233 閱讀 7913

有乙個nm格的迷宮(表示有n行、m列),其中有可走的也有不可走的,如果用1表示可以走,0表示不可以走,檔案讀入這nm個資料和起始點、結束點(起始點和結束點都是用兩個資料來描述的,分別表示這個點的行號和列號)。現在要你程式設計找出所有可行的道路,要求所走的路中沒有重複的點,走時只能是上下左右四個方向。如果一條路都不可行,則輸出相應資訊(用-l表示無路)。

請統一用 左上右下的順序拓展,也就是 (0,-1),(-1,0),(0,1),(1,0)

輸入

第一行是兩個數n,m( 1 < n , m < 15 ),接下來是m行n列由1和0組成的資料,最後兩行是起始點和結束點。

輸出

所有可行的路徑,描述乙個點時用(x,y)的形式,除開始點外,其他的都要用「->」表示方向。

如果沒有一條可行的路則輸出-1。

樣例輸入

5 61 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 15 6

樣例輸出

(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  x,y  3

對應的位置為:(x, y-1),(x-1, y),(x, y+1),(x+1, y)。所以每個點都要試探四個方向,如果沒有走過(陣列b相應的點的值為0)且可以走(陣列a相應點的值為1)同時不越界,就走過去,再看有沒有到達終點,到了終點則輸出所走的路,否則繼續走下去。

這個查詢過程用search來描述如下:

procedure search(x, y, b, p);

begin

for i:=1 to 4 do

begin

先記住當前點的位置,已走過的情況和走過的路;

如果第i個點(xl,y1)可以走,則走過去;

如果已達終點,則輸出所走的路徑並置有路可走的資訊,

否則繼續從新的點往下查詢search(xl,y1,b1,p1);

end;

end;

有些情況很明顯是無解的,如從起點到終點的矩形中有一行或一列都是為0的,明顯道路不通,對於這種情況要很快地「剪掉」多餘分枝得出結論,這就是搜尋裡所說的「剪枝」。從起點開始往下的一層層的結點,看起來如同樹枝一樣,對於其中的「枯枝」——明顯無用的節點可以先行「剪掉」,從而提高搜尋速度。

演算法分析給出了思路,照著思路來。

首先,需要乙個int ans[20][20]陣列來存放輸入的m行,n列01數字,用以記錄哪些點能不能走;

然後,需要乙個int temp[20][20] = ;陣列來記錄哪些點走沒走過,初始化全為0,表示都沒走過;

還需要乙個存放路線的容器,可以選擇vector,每次確定乙個點直接用push_back函式就好了,因為裡面的點是座標的形式(x,y),所以vector的元素可以是乙個成員為2個int值的結構體,或者用pair作為vector的元素;

再是,確定我們的遞迴函式dfs(int x, int y),輸入是位置x,y,

先確定遞迴的結束條件,當(x,y)==終點時遞迴結束,輸出路線,注意,這裡dfs的x,y引數此時已經滿足條件才會進入到dfs函式中,這個條件就是0<=x再確定遞迴函式的主體,也就是沒有達到遞迴結束條件時該怎麼處理。

temp[x]

[y]=1;

//更新(x,y)狀態,表明已經走過這個點了

for(

int i =

0; i <

4; i++

)}

上面基本上就把這道題的思路給弄清楚了,因此整體的**如下

#include

#include

#include

using

namespace std;

int m, n, flag;

int ans[20]

[20];

//記錄點可不可走

int temp[20]

[20]=

;//記錄走沒走過

int dis[4]

[2]=

,,,}

;pair<

int,

int> start, end;

vectorint,

int>> vp;

//視覺化路線

void

showvector

(vectorint,

int>> vp)

}//遞迴

void

dfs(

int x,

int y)

temp[x]

[y]=1;

for(

int i =

0; i <

4; i++)}

}int

main()

} cin >> start.first >> start.second;

cin >> end.first >> end.second;

//遞迴

vp.push_back

(make_pair

(start.first -

1, start.second -1)

);dfs(start.first -

1, start.second -1)

;if(flag ==0)

cout <<-1

<< endl;

}return0;

}

但是,我並沒有對這個思路做剪枝處理,剪枝處理比較簡單,就是在main函式裡進行遞迴之前,先查一查起點到終點這個矩陣裡面有沒有全為0的行或者列,求乙個列和和行和,判斷是否為0就行。

還有一點就是,程式返回-1還有一種情況就是找不到路線,並不僅僅是存在全為0的行或列,程式設定flag的目的就是為了解決這個問題。

問題 F 遞迴入門 走迷宮

題目描述 有乙個nm格的迷宮 表示有n行 m列 其中有可走的也有不可走的,如果用1表示可以走,0表示不可以走,檔案讀入這nm個資料和起始點 結束點 起始點和結束點都是用兩個資料來描述的,分別表示這個點的行號和列號 現在要你程式設計找出所有可行的道路,要求所走的路中沒有重複的點,走時只能是上下左右四個...

問題 F 遞迴入門 走迷宮(迷宮問題)

題目鏈結 題目描述 有乙個nm格的迷宮 表示有n行 m列 其中有可走的也有不可走的,如果用1表示可以走,0表示不可以走,檔案讀入這nm個資料和起始點 結束點 起始點和結束點都是用兩個資料來描述的,分別表示這個點的行號和列號 現在要你程式設計找出所有可行的道路,要求所走的路中沒有重複的點,走時只能是上...

5978 Problem F 遞迴入門 走迷宮

時間限制 1 sec 記憶體限制 128 mb 提交 239 解決 80 提交 狀態 討論版 命題人 外部匯入 有乙個n m格的迷宮 表示有n行 m列 其中有可走的也有不可走的,如果用1表示可以走,0表示不可以走,檔案讀入這n m個資料和起始點 結束點 起始點和結束點都是用兩個資料來描述的,分別表示...