題目:
東東有一張地圖,想通過地圖找到妹紙。地圖顯示,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出,然後分別檢查該點的 周圍 這裡的周圍...