この列は含まれています。
BFSの原理を理解するために、例を見てみましょう
。例として、迷路の中を歩くマウスを取り上げます。迷路の中の道路は複雑で複雑です。マウスが入口から入った後、マウスはどのようにして出口を見つけることができますか?
BFS:マウスのグループが迷路を歩きます。ネズミの数が無限に多いと仮定すると、このネズミのグループが入った後、各交差点で、何匹かのネズミがすべての未踏の道路を探索するために送られます。ある道路を歩いているネズミは、壁にぶつかって前進できない場合は止まります。到達した交差点が他のネズミによってすでに探索されている場合は、ネズミも止まります。明らかに、すべての道路がたどられ、出口に出くわすまで繰り返されません。このアイデアはBFSです。
特定のプログラミングでは、キューのデータ構造は通常、BFS、つまり「BFS =キュー」を実装するために使用されますが、DFSは通常、再帰、つまり「DFS=再帰」によって実装されます。
ここで、BFSとDFSをさらに比較して、BFSを深く理解しましょう。
前の講義でDFSについて学びました。
DFSは行き止まりだと思いますか?「マウスが迷路を歩く」という質問に関して、DFSの手順は、「壁にぶつかるまで最後まで進みます。壁にぶつかったら、前の手順に戻り、交差点を変更して、すべてを続行します。壁にぶつかるまでの道のり…」現在のステップが行き止まりになるか、長い迂回をするかは関係ありません。
たとえば、次の図では、「@」が始点、「*」が終点、「#」が歩くことができない壁、黒い点が次に歩くことができる交差点です。上下左右に歩くだけです。
図1迷路図
次に、開始点から終了点までの道を見つけるために、各ステップで最初に左、次に右の方法に従うと仮定すると、DFSの結果は次のようになります。
図1DFS「@」からのパスに "*"
2段で行ける道でしたが、13段でした。
しかし、BFSが可能なマウスはそれほど不器用ではありません。それははるかに賢く、あらゆる位置で「すべての方向を見て」、次に進むためのあらゆる可能な方法を試み、そして後ろの道を続けます。では、どうなるのでしょうか。次の図を見てください。
図3BFSは、「@」から「*」へのパスを検出します。
したがって、このスマートマウスのルートは次のとおり
です。1。ポイント1から開始します。
2.1の2、3の2つの隣人すべてに歩きます。このとき、始点1から1歩離れた2点(2、3)に到達しています。
3.2と3の隣人に進みます。便宜上、順番に並べてみましょう。最初に2のすべてのネイバーに移動し、(4、5、6)に移動します。
4.次に、3の隣人7と8に移動します。このとき、始点1から2歩離れた地点(4、5、6、7、8)に到達しています。そして、エンドポイント8に到達したのは、たった2つのステップです。とても賢いですね。しかし、彼の能力を示すために、マウスはすべてのポイントに到達し続けることにしました。
5.ネイバー9は4、10は5、11は6、12、13は7。このとき、始点1から3歩離れた地点(9、10、11、12、13)に到達しています。
6.さらに進むと、開始点11から4ステップ離れた点(14、15)にすべて到達します。
それだけでなく、スマートマウスは、上記の手順をキューで行うのが簡単ではないことも発見しました。フォームに記入して、キューを使用してBFSを実装する方法の手順を詳しく説明しましょう。
次に、BFSのいくつかの古典的な問題を見てみましょう。
接続の問題
接続性の判断は、グラフ理論の単純な問題です。グラフの相互接続された部分を見つけることです。これは基本的な検索です。DFSまたはBFSのいずれかを使用できます。BFSの
判断接続性の手順:
1.グラフ上の任意のポイントuからトラバースを開始し、キューに入れます。
2.キューヘッドuをポップアップし、uが検索されたことをマークしてから、uのネイバーを検索します。ネイバーが接続条件を満たしている場合は、それらをキューに入れます。
3.引き続きキューの先頭をポップアップし、検索済みのマークを付けてから、そのネイバーを検索し、接続条件を満たすものをキューに入れます。キューが空になるまで上記の手順を続けます。この時点で、接続されているすべてのポイントが見つかりました。
DFSが接続を判別するための手順は次のとおりです。
1.グラフ上の任意のポイントuからトラバースを開始し、uが検索されたことをマークします。
2.接続条件を満たす再帰的にuのネイバー。
3.再帰が終了し、接続されているすべてのポイントが見つかります。
接続に関連するブルーブリッジカップの実際の質問を見てみましょう!
トピックの説明
次のように、海域のNxNピクセル写真があります。海の場合は「。」、陸の場合は「#」です。
…
。##…
。##…
…##。
…####。
…###。
…
その中で、「上、下、左、右」の4方向につながった土地が島を形成しています。たとえば、上の写真には2つの島があります。
地球温暖化によって引き起こされる海面上昇のために、科学者たちは、島の端のピクセルが今後数十年で海水に沈むだろうと予測しています。具体的には、陸のピクセルが海に隣接している場合(上下、左、右の4つの隣接するピクセルに海があります)、水没します。
たとえば、上の写真の海域は、将来的には次のようになります。
…
…
…
…
…#…
…
…
数えてください:科学者の予測によると、写真に写っている島の数は完全に水没します。
説明を入力してください
最初の行には整数N(1≤N≤1000)が含まれています。
次のN行とN列は、海域の写真を表しています。
写真は、行1、列1、行N、および列Nのピクセルがすべて海であることを保証します。
出力の説明
答えを表す整数を出力します。
サンプル入力
7
.......
.##....
.##....
....##.
..####.
...###.
.......
サンプル出力
1
問題解決のアイデア:
どうやらそれは接続の問題です。手順は次のとおりです。
1.接続されたブロックをトラバースします(この接続されたブロックですべての「#」を検索し、すでに検索済みとしてマークします。再度検索する必要はありません);
2.次の接続されたブロックをトラバースします...;
3。すべての接続されたブロックをトラバースした後、接続されたブロックの数を数えます。
def bfs(x,y):
d = [(0,1),(0,-1),(1,0),(-1,0)]
q = [(x,y)] #用list实现队列
vis[x][y]=1
global flag
while q:
t=q.pop(0)
tx,ty = t[0],t[1]
if mp[tx][ty+1]=='#' and mp[tx][ty-1]=='#' and \
mp[tx+1][ty]=='#' and mp[tx-1][ty]=='#':
flag = 1
for i in range(4):
nx = tx+d[i][0]
ny = ty+d[i][1]
if vis[nx][ny]==0 and mp[nx][ny]=="#":
q.append((nx,ny))
vis[nx][ny]=1
n = int(input())
mp =[]
for i in range(n):
mp.append(list(input()))
vis = []
for i in range(n):
vis.append([0]*n)
ans = 0
for i in range(n):
for j in range(n):
if vis[i][j]==0 and mp[i][j]=="#":
flag = 0
bfs(i,j)
if flag == 0:
ans+=1
print(ans)
まず、このbfsの実装プロセスを解釈しましょう。
mpリストは、私たちが保存している陸と海の地図です。visリストは、mpリストと同じ仕様の判定リストであり、「#」の付いた土地が判定されたかどうかを判断するために使用されます。プログラムの複雑さを軽減します。
次に、bfs関数を入力します。dリストを使用して、土地「#」の近くにある「#」を検索します。これを方向リストと呼ぶことができます。
qリストは、判定および検索された「#」土地の座標を格納するために使用されます。qリストにパラメータが含まれていない場合、一連の土地とその周辺の土地をトラバースしたと言えます。
次に、この質問でのBFSの実装プロセスが、以前に理解したBFSの原則と同じであるかどうかを検討する必要がありますか?
このトピックの実装プロセスは、主に土地を1つずつトラバースし、次に土地を上下左右の4方向にトラバースし、すべての土地がトラバースされるまで順番に広がり続けます。プログラムは終了します。
また、前述のBFSの原則は、キューの操作で最後まで拡張しないことです。
次に、この質問の後、プログラミングを通じてBFSがどのように実装されるかを実際に学ぶ必要があるため、このプログラミングのアイデアについてさらに数回練習する必要があります。
def bfs(x,y):
d = [(0,1),(0,-1),(1,0),(-1,0)]
q = [(x,y)] #用list实现队列
vis[x][y]=1
global flag
while q:
t=q.pop(0)
tx,ty = t[0],t[1]
if mp[tx][ty+1]=='#' and mp[tx][ty-1]=='#' and \
mp[tx+1][ty]=='#' and mp[tx-1][ty]=='#':
flag = 1
for i in range(4):
nx = tx+d[i][0]
ny = ty+d[i][1]
if vis[nx][ny]==0 and mp[nx][ny]=="#":
q.append((nx,ny))
vis[nx][ny]=1