[파이썬] 백준 17244 : 아맞다우산 (골드2)
17244번: 아맞다우산
경재씨는 저녁 약속을 가기 전 챙기지 않은 물건들이 있는 지 확인하고 있다. 필요한 물건은 전부 챙긴 것 같았고 외출 후 돌아오는 길에 경재씨는 외쳤다. "아 맞다 우산!!!" 경재 씨는 매번 외출
www.acmicpc.net
문제
풀이
0. 방향성 생각
기본적으로 DP에서 하던거처럼 상태를 나눈다. 물건의 개수가 늘어갈수록 상대가 2배로 늘어나니
bitmask를 통해서 간편하게 처리한다는게 아이디어
1. 입력
from collections import deque
import sys
input = lambda : sys.stdin.readline().rstrip()
w,h = map(int,input().split())
arr = [list(input()) for _ in range(h)]
table,count = {},0
for i in range(h):
for j in range(w):
if arr[i][j] == 'S':
arr[i][j] = '.'
start = (j,i)
if arr[i][j] == 'X':
table[(j,i)] = count
count += 1
입력을 다 받고나서 시작점 start를 저장한다.
물건의 위치는 table에 저장하고 몇 개인지 카운트한다.
2. visit 초기화
step = [[1,-1,0,0],[0,0,1,-1]]
x,y = start
visit = [[[-1]*w for _ in range(h)] for _ in range(1<<count)]
visit[0][y][x] = 0
q = deque([(x,y,0)])
visit[상태][열][행] 순서대로 시작.
큐에는 x,y좌표와 아무것도 찾지 않은 상태인 0을 넣어준다.
3. 그래프 탐색
while q:
x,y,bit = q.popleft()
for i in range(4):
nx = x + step[0][i]
ny = y + step[1][i]
if 0<=nx<w and 0<=ny<h and visit[bit][ny][nx] == -1 and arr[ny][nx] != '#':
if arr[ny][nx] == 'X' :
nbit = bit | 1<<table[(nx,ny)]
visit[nbit][ny][nx] = visit[bit][y][x] + 1
q.append((nx,ny,nbit))
else:
nbit = bit
visit[bit][ny][nx] = visit[bit][y][x] + 1
q.append((nx,ny,nbit))
if arr[ny][nx] == 'E' and nbit == 2**count-1 :
print(visit[nbit][ny][nx])
break
X를 찾으면 상태가 변한다. table에서 물건마다 부여한 번호만큼 shift한 후 방문처리를 OR 연산으로 해준다.
'X'가 아닌 경우에는 상태가 변하지 않으므로
전체코드
from collections import deque
import sys
input = lambda : sys.stdin.readline().rstrip()
w,h = map(int,input().split())
arr = [list(input()) for _ in range(h)]
table,count = {},0
for i in range(h):
for j in range(w):
if arr[i][j] == 'S':
arr[i][j] = '.'
start = (j,i)
if arr[i][j] == 'E':
end = (j,i)
if arr[i][j] == 'X':
table[(j,i)] = count
count += 1
step = [[1,-1,0,0],[0,0,1,-1]]
x,y = start
visit = [[[-1]*w for _ in range(h)] for _ in range(1<<count)]
visit[0][y][x] = 0
q = deque([(x,y,0)])
while q:
x,y,bit = q.popleft()
for i in range(4):
nx = x + step[0][i]
ny = y + step[1][i]
if 0<=nx<w and 0<=ny<h and visit[bit][ny][nx] == -1 and arr[ny][nx] != '#':
if arr[ny][nx] == 'X' :
nbit = bit | 1<<table[(nx,ny)]
visit[nbit][ny][nx] = visit[bit][y][x] + 1
q.append((nx,ny,nbit))
else:
nbit = bit
visit[bit][ny][nx] = visit[bit][y][x] + 1
q.append((nx,ny,nbit))
if arr[ny][nx] == 'E' and nbit == 2**count-1 :
print(visit[nbit][ny][nx])
break
코멘트
DP에서 하던 발상이랑 비슷해서 첫 비트마스크 풀이인데도 나쁘지 않게 푼 듯.
많은 상태도를 bit연산으로 처리하는거 이외의 발상은 똑같다.
'Algorithm > Graph' 카테고리의 다른 글
[파이썬] 백준 프로그래머스 : 합승 택시 요금 (Lv3) (0) | 2023.08.16 |
---|---|
[파이썬] 백준 1504 : 특정한 최단 경로(골드4) (0) | 2023.08.16 |
[파이썬] 백준 2481 : 해밍 경로 (골드2) (0) | 2023.08.12 |
[파이썬] 백준 9019 : DSLR (골드4) (0) | 2023.08.03 |
[파이썬] 백준 17090 : 미로 탈출하기 (골드3) (0) | 2023.07.31 |
[파이썬] 백준 1525 : 퍼즐 (골드2) (0) | 2023.07.30 |
[파이썬] 프로그래머스 : 단어 변환 (Lv.2) (0) | 2023.07.20 |
댓글