atcoder arc C - 器物損壊!高橋君の勉強
・問題:
atcoder.jp
・参考:
Submission #16162979 - AtCoder Regular Contest 005
AtCoder ARC 005 C - 器物損壊!高橋君 (0-1 BFS) (水色) - けんちょんの競プロ精進記録
・0-1BFS:
01-BFSのちょっと丁寧な解説 - ARMERIA
・ダイクストラ法:
グラフ理論⑤(ダイクストラのアルゴリズム) - YouTube
・0-1BFSを使う。壁の有無で0,1を重さとしてBFSするものをいう。ダイクストラ法の重さが0,1になったもので、0のときはdequeの左から入れて1のときは右から入れる。こうすると0の壁がないルートを優先的に選んで進む(popleftは左から取ってくるので)。
・やり方:
Submission #16162979 - AtCoder Regular Contest 005のやり方を参考にする。s(スタート)からg(ゴール)までBFSをする。distに壁を壊した回数を入れて(無限大で初期化)、移動した座標が'#'なら前の座標+1する(プログラムのd=dist[x][y]+wallの部分)。最終的にdist[gx][gy]が2以下ならOK。
・注意点:"Yes","No"ではなく"YES","NO"と出力することを忘れずに。
ここからは参考の記事の2つのやり方をやってみる。まずSubmission #16162979 - AtCoder Regular Contest 005の場合
from collections import deque H,W=map(int,input().split()) field=[input() for _ in range(H)] dx=[1,0,-1,0] dy=[0,1,0,-1] #スタートの座標とゴールの座標の特定。 for i in range(H): for j in range(W): if field[i][j]=='s': sx=i sy=j if field[i][j]=='g': gx=i gy=j #壁を壊した回数がdist。大きい値で初期化 dist=[[10**18 for _ in range(W)] for _ in range(H)] #print(dist) #スタートはdist=0、queにスタートを追加 dist[sx][sy]=0 que=deque() que.append((sx,sy)) #print(que) #queがからになるまで幅優先探索をやる while len(que)!=0: x,y=que.popleft() #queの先頭のペアを取り出す #移動 for i in range(4): next_x=x+dx[i] next_y=y+dy[i] #場外はスルー if next_x<0 or next_x>=H or next_y<0 or next_y>=W: continue wall=(field[next_x][next_y]=='#') #field[next_x][next_y]=='#'なら1、違ったら0 d=dist[x][y]+wall #壁があったら前の座標足す1。 #distが更新できるならdにする。 if d<dist[next_x][next_y]: dist[next_x][next_y]=d #壁があったらqueの後ろから足す、なかったら前からいれる if wall: que.append((next_x,next_y)) else: que.appendleft((next_x,next_y)) print("YES" if dist[gx][gy]<=2 else "NO")
次にAtCoder ARC 005 C - 器物損壊!高橋君 (0-1 BFS) (水色) - けんちょんの競プロ精進記録
from collections import deque H,W=map(int,input().split()) field=[input() for _ in range(H)] dx=[1,0,-1,0] dy=[0,1,0,-1] #スタートの座標とゴールの座標の特定。 for i in range(H): for j in range(W): if field[i][j]=='s': sx=i sy=j if field[i][j]=='g': gx=i gy=j #壁を壊した回数がdist。大きい値で初期化 dist=[[10**18 for _ in range(W)] for _ in range(H)] #print(dist) #スタートはdist=0、queにスタートを追加 dist[sx][sy]=0 que=deque() que.append((sx,sy)) #print(que) #queがからになるまで幅優先探索をやる while len(que)!=0: x,y=que.popleft() #queの先頭のペアを取り出す #移動 for i in range(4): next_x=x+dx[i] next_y=y+dy[i] #場外はスルー if next_x<0 or next_x>=H or next_y<0 or next_y>=W: continue #壁があって、前の座標のdist+1(壁のぶん+1する)のほうが次のよりも小さいとqueの後ろからいれる if field[next_x][next_y]=='#': if dist[next_x][next_y]>dist[x][y]+1: dist[next_x][next_y]=dist[x][y]+1 que.append((next_x,next_y)) #壁がないとき、queの前から。 else: if dist[next_x][next_y]>dist[x][y]: dist[next_x][next_y]=dist[x][y] que.appendleft((next_x,next_y)) print("YES" if dist[gx][gy]<=2 else "NO")