白駿2206号:壁を破って進む
壁を破壊して移動
白駿2206号:壁を破って進む
アイデア
まず思いついた方法はすべての壁(1)を道(0)に変えてBFSを行い,壁の最大個数はNM個であるため時間的複雑度はO(N^2 M^2)であり,解くことができない.
すべての壁は破ることができないので、道を歩いて壁に出会ったとき、もしあなたが壁を破ることがなければ、あなたはそれを破ることができて、もしあなたがそれを破ったことがあるならば、あなたはそれを探求することができません.しかし、問題があります.私は壁を破って来たのか、それともこのように来たのか分からない.壁にぶつかった状態を記録してこそ解くことができる.
どうすれば壁を壊した状態を記録できますか?BFSを行う場合,キューに次のノードの情報を挿入するプロセスがある.同時に「壁を破って1、壁を破らずに0」の状態を提供します.
そして、「壁を破って来た場合のみ使用するグラフ」を別途作成して使用します.元の図形から壁を打ち砕くと、元の図形の壁を残し、壁を打ち砕いてから使用する図形の同じ位置の壁だけを打ち砕き、そこから探索を開始します.
では、壁を割るたびにグラフを作り直しますか?考えてもいいですが、もう一つ作って使うだけでいいです.
現在のノードに対して、上下左右4方向のノードから適切なノードを選択してキューに入れます.このとき1は壁なので、ナビゲートは行いません.(元の図形の位置を見てみましょう.壁を割った人もいるかもしれませんから)1ではなく、他の数字であれば、「現在のノードの中の数字」に比べて1でなければ(通ったばかりの長さであれば差は1であるはずです.数字を1つずつ加算して、どれだけの格を移動したかを記録していますので)探索します.つまり、再利用できるということです.
言葉で説明するのはちょっと難しいですが、注釈のコードを見ると分かりやすいかも・・・from collections import deque
dx = [0, 0, 1, -1]
dy = [1, -1, 0, 0]
N, M = map(int, input().split())
graph = [[[] for _ in range(N)] for _ in range(2)]
for i in range(N):
str = input()
for c in str:
for z in range(2):
graph[z][i].append(int(c))
def bfs(graph):
res = 987654321
q = deque()
q.append((0, 0, 0))
graph[0][0][0] = 1
while q:
z, y, x = q.popleft()
if y == N - 1 and x == M - 1:
res = min(res, graph[z][y][x])
# 벽을 부수고 온 경우
if z == 1:
for i in range(4):
ny, nx = y + dy[i], x + dx[i]
# 맵 밖으로 벗어났을 때
if ny < 0 or nx < 0 or ny >= N or nx >= M:
continue
# 벽 만났을 때 (원본 그래프로 체크)
elif graph[0][ny][nx] == 1:
continue
# 길 만났을 때
elif graph[1][ny][nx] == 0:
graph[1][ny][nx] = graph[1][y][x] + 1
q.append((1, ny, nx))
# 누가 지나온 길 만났을 때
else:
# 내가 방금 밟은거 아니면
if graph[1][ny][nx] != graph[1][y][x] + 1:
graph[1][ny][nx] = graph[1][y][x] + 1
else:
for i in range(4):
ny, nx = y + dy[i], x + dx[i]
# 맵 밖으로 벗어났을 때
if ny < 0 or nx < 0 or ny >= N or nx >= M:
continue
# 벽 만났을 때 (원본 그래프로 체크)
elif graph[0][ny][nx] == 1:
# 부순 적 없는 벽이면
if graph[1][ny][nx] == 1:
graph[1][ny][nx] = graph[0][y][x] + 1
q.append((1, ny, nx))
# 길 만났을 때
elif graph[0][ny][nx] == 0:
graph[0][ny][nx] = graph[0][y][x] + 1
q.append((0, ny, nx))
# 지나온 길 만났을 때
else:
continue
return res
ans = bfs(graph)
if ans == 987654321:
print(-1)
else:
print(ans)
おしゃべり
まる3日間私を苦しめていた.グラフの問題をもっと解くべきだでは、奇抜な考えはどう思いますか.psが上手な人は羨ましいですね
Reference
この問題について(白駿2206号:壁を破って進む), 我々は、より多くの情報をここで見つけました
https://velog.io/@ks1ksi/백준-2206번-벽-부수고-이동하기
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
from collections import deque
dx = [0, 0, 1, -1]
dy = [1, -1, 0, 0]
N, M = map(int, input().split())
graph = [[[] for _ in range(N)] for _ in range(2)]
for i in range(N):
str = input()
for c in str:
for z in range(2):
graph[z][i].append(int(c))
def bfs(graph):
res = 987654321
q = deque()
q.append((0, 0, 0))
graph[0][0][0] = 1
while q:
z, y, x = q.popleft()
if y == N - 1 and x == M - 1:
res = min(res, graph[z][y][x])
# 벽을 부수고 온 경우
if z == 1:
for i in range(4):
ny, nx = y + dy[i], x + dx[i]
# 맵 밖으로 벗어났을 때
if ny < 0 or nx < 0 or ny >= N or nx >= M:
continue
# 벽 만났을 때 (원본 그래프로 체크)
elif graph[0][ny][nx] == 1:
continue
# 길 만났을 때
elif graph[1][ny][nx] == 0:
graph[1][ny][nx] = graph[1][y][x] + 1
q.append((1, ny, nx))
# 누가 지나온 길 만났을 때
else:
# 내가 방금 밟은거 아니면
if graph[1][ny][nx] != graph[1][y][x] + 1:
graph[1][ny][nx] = graph[1][y][x] + 1
else:
for i in range(4):
ny, nx = y + dy[i], x + dx[i]
# 맵 밖으로 벗어났을 때
if ny < 0 or nx < 0 or ny >= N or nx >= M:
continue
# 벽 만났을 때 (원본 그래프로 체크)
elif graph[0][ny][nx] == 1:
# 부순 적 없는 벽이면
if graph[1][ny][nx] == 1:
graph[1][ny][nx] = graph[0][y][x] + 1
q.append((1, ny, nx))
# 길 만났을 때
elif graph[0][ny][nx] == 0:
graph[0][ny][nx] = graph[0][y][x] + 1
q.append((0, ny, nx))
# 지나온 길 만났을 때
else:
continue
return res
ans = bfs(graph)
if ans == 987654321:
print(-1)
else:
print(ans)
Reference
この問題について(白駿2206号:壁を破って進む), 我々は、より多くの情報をここで見つけました https://velog.io/@ks1ksi/백준-2206번-벽-부수고-이동하기テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol