白駿2206破壁機


白俊2206号破壁問題です.
https://www.acmicpc.net/problem/2206

パイ
from collections import deque

N, M = map(int, input().split())

walls = []
board = []
for i in range(N):  
  board.append([int(_) for _ in input()])

for i in range(N):
  for v in range(M):
    if board[i][v] == 1:
      walls.append([i,v])

dy = [-1, 0, 1, 0]
dx = [0, 1, 0, -1]
INF = float('inf')

def bfs(board):
  deq = deque()
  deq.append([0,0,1,True])  
  visited =[[INF for _ in range(M)] for _ in range(N)]
  crush_visited =[[INF for _ in range(M)] for _ in range(N)]
  result = []
  while deq:
    r, c, cost, wall = deq.popleft()
    if [r, c] == [N-1, M-1]:
      result.append(cost)
    else:
      for i in range(4):
        new_r = r + dy[i]
        new_c = c + dx[i] 

        if new_r < 0 or new_r >= N or new_c < 0 or new_c >= M:
          continue
        
        if wall:
          prev_cost = visited[new_r][new_c]
        else:
          prev_cost = crush_visited[new_r][new_c]

        if board[new_r][new_c] == 0:
          if prev_cost > cost+1:
            deq.append([new_r, new_c, cost+1, wall])
            if wall:
              visited[new_r][new_c] = cost+1
            else:
              crush_visited[new_r][new_c] = cost+1
        else:
          if wall == True: 
            if prev_cost > cost+1:
              deq.append([new_r, new_c, cost+1, False])
              crush_visited[new_r][new_c] = cost+1
        
  if len(result) == 0:
    return -1
  else:
    return min(result)


print(bfs(board))

に感銘を与える


思ったより難しかったです.
最初に、すべての壁をリストに保存し、壁をクリアし、bfsを使用して最小値を検索します.
でもやっぱりタイムアウト.
最終的に,bfs過程で破壁挙動が必要であることを認識した.
我々は,一度しか壁を破ることができないので,壁を破る機会のあるbfsと分離することができると考えている.
このため、アクセスでコストを保存および比較する場合、

破壁グループvs破壁グループを破る機会がある


こうして分けて保存しました
最後に,抽出コストが最も低い場合を決定し,不可能な場合に−1を返す.