SDU week2作業 BFS 的兩道例題

2021-10-03 13:00:11 字數 3797 閱讀 7638

題目:

東東有一張地圖,想通過地圖找到妹紙。地圖顯示,0表示可以走,1表示不可以走,左上角是入口,右下角是妹紙,這兩個位置保證為0。既然已經知道了地圖,那麼東東找到妹紙就不難了,請你編乙個程式,寫出東東找到妹紙的最短路線。

input:

輸入是乙個5 × 5的二維陣列,僅由0、1兩數字組成,表示法陣地圖。

output:

輸出若干行,表示從左上角到右下角的最短路徑依次經過的座標,格式如樣例所示。資料保證有唯一解。

**思路:**主要問題就是如何從起點找到到終點的路徑,使用的是bfs,每次都是由當前節點向外拓展一層,符合條件的加入,直到遇到終點為止。

總結:

這算是乙個比較典型的bfs問題,因此在這裡由這道題總結一下用bfs 做題的一般性情況。bfs常用的資料結構是佇列,首先就是將起點放入佇列,然後判定條件!(q.empty),然後講佇列首元素取出來判定終點,緊接著就是以當前元素為起點,向外拓展一層,將新的元素加入佇列,也可以稱為是狀態轉移。至於具體的就需要判斷新的元素是否符合加入的條件,在本題中就是沒有超出邊界範圍,並且之前沒有訪問過。

以上是總體上的內容,接下來就將一下這個題細節性問題。

(1)為方便上下左右四個狀態,可以在原本的範圍上拓寬一周,然後便於邊界點的判斷,由55的方陣變成了77的方陣,順便為便於標記到達情況,可將四周的牆標記為-1 ,表示不可達,未經過點是0 ,已到達點是1。

(2)如何記錄路徑的問題:我在這個實驗中是找到了看兩種方法。第一種,用二維陣列表示前向,在新拓展一層點的時候,記錄這個點的前向點:pre[x][y]=now;

然後利用遞迴的方法輸出:

void

output

(point now)

printf

("(%d, %d)\n"

,now.x-

1,now.y-1)

;}

假設題目是不計算具體的路徑而只要求輸出需要多少步的時候,可以利用這樣陣列的思想,記錄距離:

dis[x]

[y]=dis[now.x]

[now.y]+1

;

直接輸出最後的距離就是總距離。

第二種方法是仍然用陣列記錄前向:pre[xx][yy]=point(x,y); //記錄前向

然後由於這樣是只能從後往前記錄,但是需要從前往後輸出,此時就利用棧輸出,已知最終的點座標,依次壓入棧,最後從棧中彈出輸出。

stack s;

int xx=

4,yy=4;

while

(true

)while

(!s.

empty()

)

**:

//地圖加上牆這一邊界

//定義每次走的四個方向

//記錄前向,這個點的上乙個點是什麼

#include

#include

#include

#include

using

namespace std;

const

int maxn=7;

struct point*/}

; point pre[7]

[7];

int dx=

;int dy=

;int maze[maxn]

[maxn]

;// 0 1 2 3 4 5 6

bool vis[maxn]

[maxn]=;

int dis[maxn]

[maxn]=;

void

output

(point now)

printf

("(%d, %d)\n"

,now.x-

1,now.y-1)

;}void

bfs(

)for

(int i=

0;i<

4;i++)}

}}intmain()

}bfs()

;//printf("%d",dis[5][5]);

return0;

}

**題目:**倒水問題 「fill a」 表示倒滿a杯,"empty a"表示倒空a杯,「pour a b」 表示把a的水倒到b杯並且把b杯倒滿或a倒空。

input:

輸入包含多組資料。每組資料輸入 a, b, c 資料範圍 0 < a <= b 、c <= b <=1000 、a和b互質。

output:

你的程式的輸出將由一系列的指令組成。這些輸出行將導致任何乙個罐子正好包含c單位的水。每組資料的最後一行輸出應該是「success」。輸出行從第1列開始,不應該有空行或任何尾隨空格。

思路:這個題目 我感覺隱含了一些資訊,比如水的**是無限的,可以一直從飲水機中倒水,如果要將某個杯子倒空的話,不必關心水是倒在**。然後這個題就是2個杯子,針對其中水的不同情況,有六種轉移狀態。整個過程的起點是ab杯皆空,終點是a 杯或者b杯的水為c,在每一次狀態下,都有可能存在6種能轉移的狀態(當然中間有不合適的,不合適的捨棄即可)。

同時因為要求輸出每個過程的操作,因此需要記錄下這一步使怎麼得來的,因為只有6種情況,因此可以考慮在結構體種加入狀態,根據不同的操作,在驗證是否加入的時候更改狀態。

輸出也是仿照上例,通過前向陣列,遞迴輸出。

總結:

因為這兩個題都分別屬於bfs 的顯式和隱式題,在這裡總結一下,什麼樣的題可以考慮用bfs 求解,分析有以下特徵

(1)有起點和終點

(2)起點由有限次的且每次有限個的狀態轉移可以到達終點

(3)求最短路徑的時候

**:

#include

#include

#include

#include

using

namespace std;

const

int maxn=

1001

;struct node

bool

operator==(

const node &s)

const};

bool vis[maxn]

[maxn]

;node pre[maxn]

[maxn]

;void

trans

(node t)

}void

output

(node t)

}void

bfs(

int a,

int b,

int c)

if(s.b//b中水不滿,倒滿b杯中的水 fill b }if

(s.b>0)

//b中有水,倒空b杯中的水 }if

(s.a//a中水不滿,倒滿a杯中的水 }if

(s.a>0)

//a中有水,倒空a杯中的水 }if

(s.a!=

0&&s.b//a中有水且b中水不滿,考慮a杯倒入b杯

}else}}

if(s.b!=

0&&s.a//a中有水且b中水不滿,考慮b杯倒入a杯

}else}}

}}intmain()

return0;

}

Week2 作業A 迷宮 bfs

輸入5 5矩陣,1表示牆,0表示可走。找出從左上角到右下角的最短路徑所經過的座標 輸入保證有唯一解 bool型二維陣列vis儲存輸入的01矩陣,1表示牆,0表示可走。map from儲存每乙個經過的座標的前驅結點座標。queue q儲存每一層擴充套件時的中心結點。為方便層層擴充套件時遍歷上下左右四個...

week2作業題 bfs迷宮問題 bfs倒水問題

東東有一張地圖,想通過地圖找到妹紙。地圖顯示,0表示可以走,1表示不可以走,左上角是入口,右下角是妹紙,這兩個位置保證為0。既然已經知道了地圖,那麼東東找到妹紙就不難了,請你編乙個程式,寫出東東找到妹紙的最短路線。input 輸入是乙個5 5的二維陣列,僅由0 1兩數字組成,表示法陣地圖。outpu...

week2作業 bfs的簡單應用 倒水問題

一道bfs的簡單應用 與迷宮題十分類似 用到的資料結構 主要思路 bfs操作 先將起始狀態push到佇列中並作標記 在集合中標記,不同於上一道迷宮題目,迷宮的位置可以窮盡但本題水的狀態過多,再用如二維陣列來記錄顯然不合適,遂使用集合 分別將佇列中元素依次pop出,然後分別檢查該點的 周圍 這裡的周圍...