[파이썬] 백준 5213 : 과외맨 (골드2)
5213번: 과외맨
첫째 줄에 N이 주어진다. (1 ≤ N ≤ 500) 다음 줄부터 N*N-N/2줄(/는 정수 나눗셈이다)에는 두 양의 Ai와 Bi가 주어진다. (1 ≤ Ai, Bi ≤ 6, 1 ≤ i ≤ N * N - N / 2) 타일 i의 왼쪽에 쓰여 있는 숫자는 Ai, 오른
www.acmicpc.net
문제
풀이
0. 방향성 생각
- 타일 넘버링을 잘 하기.
- 역추적을 해야한다.역추적 배열을 하나 더 만들어서 새로 갱신하는 경우에 온 경로에 이전 좌표를 갱신.
1. array 만들기
from collections import deque
import sys
input = lambda : sys.stdin.readline().rstrip()
arr = []
n = int(input())
for h in range(n):
row = []
if not h%2:
for _ in range(n) : row.extend(list(map(int,input().split())))
else:
for _ in range(n-1) : row.extend(list(map(int,input().split())))
row = [0]+row+[0]
arr.append(row)
- 배열 받아주기
2. tile 넘버링
tile = [[-1]*2*n for _ in range(n)]
count = 1
for h in range(n):
temp = 0
for w in range(2*n):
if h%2 and (w==0 or w==2*n-1):
continue
else :
tile[h][w] = count
temp += 1
if temp==2:
count += 1
temp = 0
- 타일넘버링 규칙은 문제에 서술돼있으니 자세한 설명은 생략한다.
- 사실 위에 arr이랑 한 for문으로 구성할 수도 있는데, 고치기 귀찮아서 패스.
3. visit, trace 배열 생성
dire = [(1,0),(0,1),(-1,0),(0,-1)]
inf = 1e6
visit = [[inf]*2*n for _ in range(n)]
visit[0][0] = 1
trace = [[(-1,-1)]*2*n for _ in range(n)]
trace[0][0] = (0,0)
- 배열을 생성하고 시작점 초기화해주기.
4. BFS
max_tile,max_tile_loc = -1,(0,0)
q = deque([(0,0)])
while q:
x,y = q.popleft()
t = visit[y][x]
for dx,dy in dire:
nx,ny = x+dx,y+dy
if 0<=nx<2*n and 0<=ny<n:
if tile[y][x] == tile[ny][nx] and t < visit[ny][nx]:
q.append((nx,ny))
visit[ny][nx] = t
trace[ny][nx] = (x,y)
if max_tile < tile[ny][nx]:
max_tile = tile[ny][nx]
max_tile_loc = (nx,ny)
else :
if arr[y][x] == arr[ny][nx] and t+1 < visit[ny][nx]:
q.append((nx,ny))
visit[ny][nx] = t+1
trace[ny][nx] = (x,y)
if max_tile < tile[ny][nx]:
max_tile = tile[ny][nx]
max_tile_loc = (nx,ny)
- 가장 멀리 도달한 타일을 찾기 위해서 max_tile과 그 좌표 loc를 기록한다. (사실 시간초과나서 이 부분을 추가했었는데 다른 부분 수정하면서 없어짐. 큰 차이 없을듯?)
- 타일이 같은 경우에는 새로 갱신하는 경우에 넣어준다.
- 타일이 같지 않은 경우에는 인접 숫자가 같고 새로 갱신하는 경우에 넣어준다.
- 갱신하면서 max_tile과 좌표 기록하기
5. 경로 추적
def path(a,b):
ans = [tile[b][a]]
x,y = trace[b][a]
while True:
if tile[y][x] == 1:
ans.append(tile[y][x])
break
if tile[y][x] != ans[-1]:
ans.append(tile[y][x])
x,y = trace[y][x]
return ans[::-1]
a,b = max_tile_loc
answer = path(a,b)
print(len(answer))
print(*answer)
- 1번 타일이 나올 때 까지 경로 추적해주기. 재귀로 풀 수도 있지만 그냥 진행.
- 같은 타일인 경우에는 추가하지 않는다.
전체코드
from collections import deque
import sys
input = lambda : sys.stdin.readline().rstrip()
arr = []
n = int(input())
for h in range(n):
row = []
if not h%2:
for _ in range(n) : row.extend(list(map(int,input().split())))
else:
for _ in range(n-1) : row.extend(list(map(int,input().split())))
row = [0]+row+[0]
arr.append(row)
tile = [[-1]*2*n for _ in range(n)]
count = 1
for h in range(n):
temp = 0
for w in range(2*n):
if h%2 and (w==0 or w==2*n-1):
continue
else :
tile[h][w] = count
temp += 1
if temp==2:
count += 1
temp = 0
dire = [(1,0),(0,1),(-1,0),(0,-1)]
inf = 1e6
visit = [[1e9]*2*n for _ in range(n)]
visit[0][0] = 1
trace = [[(-1,-1)]*2*n for _ in range(n)]
trace[0][0] = (0,0)
max_tile,max_tile_loc = -1,(0,0)
q = deque([(0,0)])
while q:
x,y = q.popleft()
t = visit[y][x]
for dx,dy in dire:
nx,ny = x+dx,y+dy
if 0<=nx<2*n and 0<=ny<n:
if tile[y][x] == tile[ny][nx] and t < visit[ny][nx]:
q.append((nx,ny))
visit[ny][nx] = t
trace[ny][nx] = (x,y)
if max_tile < tile[ny][nx]:
max_tile = tile[ny][nx]
max_tile_loc = (nx,ny)
else :
if arr[y][x] == arr[ny][nx] and t+1 < visit[ny][nx]:
q.append((nx,ny))
visit[ny][nx] = t+1
trace[ny][nx] = (x,y)
if max_tile < tile[ny][nx]:
max_tile = tile[ny][nx]
max_tile_loc = (nx,ny)
def path(a,b):
ans = [tile[b][a]]
x,y = trace[b][a]
while True:
if tile[y][x] == 1:
ans.append(tile[y][x])
break
if tile[y][x] != ans[-1]:
ans.append(tile[y][x])
x,y = trace[y][x]
return ans[::-1]
a,b = max_tile_loc
answer = path(a,b)
print(len(answer))
print(*answer)
코멘트
이전에 못풀었던 문제. 디버깅해서 풀었다.
공부를 좀 하고 보니까 코드도 비효율적으로 짠 부분이 많아서 살짝 수정.
최적화가 좀 덜돼서 시간초과가 몇 번 발생했지만, 플레 문제나 다른 효율성 위주 문제에서 최적화 하는 발상이 도움이 돼서 금방 풀었다.
'Algorithm > Graph' 카테고리의 다른 글
[파이썬] 백준 1194: 달이 차오른다, 가자. (골드1) (0) | 2023.12.19 |
---|---|
[파이썬] 백준 5719 : 거의 최단 경로 (플레5) (0) | 2023.12.19 |
[파이썬] 백준 2021 : 최소 환승 경로 (골드2) (0) | 2023.12.17 |
[파이썬] 백준 16441 : 아기돼지와 늑대 (골드3) (0) | 2023.12.17 |
[파이썬] 백준 2887 : 행성터널 (플레5) (0) | 2023.12.16 |
[파이썬] 백준 16933 : 벽 부수고 이동하기 3 (골드1) (0) | 2023.12.16 |
[파이썬] 백준 14442 : 벽 부수고 이동하기 2 (골드3) (0) | 2023.12.15 |
댓글