일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 코딩테스트실력진단
- KT포트포워딩
- 이것이자바다확인문제
- 이것이자바다9장
- 2019카카오코테
- 백준
- 백준괄호
- 딥러닝
- 확인문제
- 합성곱연산
- 웹개발기초
- BOJ1655
- 코테
- 이것이자바다
- java
- 윤곽선검출
- BOJ
- 백준가운데를말해요
- 백준온라인저지
- 백준9012
- 백준평범한배낭
- 운영체제
- 코드트리
- 컴퓨터비전
- 카카오코테
- 스파르타코딩클럽
- 가운데를말해요
- 백준스택
- 백준10828
- 냅색알고리즘
- Today
- Total
코딩하는 락커
[BOJ 6087] 레이저 통신 - Python 풀이 본문
링크: https://www.acmicpc.net/problem/6087
문제
크기가 1×1인 정사각형으로 나누어진 W×H 크기의 지도가 있다. 지도의 각 칸은 빈 칸이거나 벽이며, 두 칸은 'C'로 표시되어 있는 칸이다.
'C'로 표시되어 있는 두 칸을 레이저로 통신하기 위해서 설치해야 하는 거울 개수의 최솟값을 구하는 프로그램을 작성하시오. 레이저로 통신한다는 것은 두 칸을 레이저로 연결할 수 있음을 의미한다.
레이저는 C에서만 발사할 수 있고, 빈 칸에 거울('/', '\')을 설치해서 방향을 90도 회전시킬 수 있다.
아래 그림은 H = 8, W = 7인 경우이고, 빈 칸은 '.', 벽은 '*'로 나타냈다. 왼쪽은 초기 상태, 오른쪽은 최소 개수의 거울을 사용해서 두 'C'를 연결한 것이다.
7 . . . . . . . 7 . . . . . . .
6 . . . . . . C 6 . . . . . /-C
5 . . . . . . * 5 . . . . . | *
4 * * * * * . * 4 * * * * * | *
3 . . . . * . . 3 . . . . * | .
2 . . . . * . . 2 . . . . * | .
1 . C . . * . . 1 . C . . * | .
0 . . . . . . . 0 . \-------/ .
0 1 2 3 4 5 6 0 1 2 3 4 5 6
입력
첫째 줄에 W와 H가 주어진다. (1 ≤ W, H ≤ 100)
둘째 줄부터 H개의 줄에 지도가 주어진다. 지도의 각 문자가 의미하는 것은 다음과 같다.
- .: 빈 칸
- *: 벽
- C: 레이저로 연결해야 하는 칸
'C'는 항상 두 개이고, 레이저로 연결할 수 있는 입력만 주어진다.
출력
첫째 줄에 C를 연결하기 위해 설치해야 하는 거울 개수의 최솟값을 출력한다.
예제 입력 1
7 8
.......
......C
......*
*****.*
....*..
....*..
.C..*..
.......
예제 출력 1
3
코드
import sys
import heapq
W, H = map(int, sys.stdin.readline().split())
grid = [sys.stdin.readline().rstrip() for _ in range(H)]
visited = [[False] * W for _ in range(H)]
dx, dy = [-1, 0, 1, 0], [0, -1, 0, 1]
s_x, s_y, e_x, e_y = -1, -1, -1, -1
result = sys.maxsize
# 출발 지점인 s_x, s_y와 도착 지점인 e_x, e_y를 설정해주는 부분
def init():
global s_x, s_y, e_x, e_y
pos = []
for i in range(H):
for j in range(W):
if grid[i][j] == "C":
pos.append(i)
pos.append(j)
if len(pos) == 4: break
if len(pos) == 4: break
s_x, s_y, e_x, e_y = pos
def in_range(x,y):
return 0 <= x < H and 0 <= y < W
def can_go(x,y):
if not in_range(x, y): return False
if visited[x][y]: return False
if grid[x][y] == "*": return False
else: return True
def dijkstra():
global result
# heap으로 사용되는 변수 q에는 (cnt, dist, x, y, z)가 저장됨
# cnt: 방향을 전환한 횟수
# dist: 출발지점(s_x, s_y)로부터의 거리
# x, y, z: x좌표, y좌표, 직전 좌표에서의 방향
q = [(0, 0, s_x, s_y, -1)]
while q:
cnt, dist, x, y, z = heapq.heappop(q)
if x == e_x and y == e_y:
result = cnt
break
visited[x][y] = True
for i in range(4):
new_x, new_y = x+dx[i], y+dy[i]
if can_go(new_x, new_y):
if z != -1 and z != i:
heapq.heappush(q, (cnt+1, dist+1, new_x, new_y, i))
else:
heapq.heappush(q, (cnt, dist+1, new_x, new_y, i))
init()
dijkstra()
print(result)
결과

풀이
처음에는 평범한 bfs를 사용하여 풀려고 하다가 cnt, 즉 방향을 전환한 횟수가 적은 순서대로 정렬하는 자료구조가 필요할 것 같아서 heapq를 사용하게 되었고 다익스트라와 유사한 알고리즘이 됨.
거리를 기준으로 가까운 순서대로 방문하는 것이 아니라 구하고자 하는 답인 방향 전환이 적은 순서대로 방문하는 것이 관건인 문제였음.
골드3 짜리 문제를 답 안보고 풀어서 뿌듯하다ㅎㅎ
'💯 코딩테스트 > [2021~] 💯 코딩테스트' 카테고리의 다른 글
[BOJ 17406] 배열 돌리기4 - Python 풀이 (2) | 2022.12.23 |
---|---|
[BOJ 16973] 직사각형 탈출 - Python 풀이 (0) | 2022.12.17 |
[BOJ 2267] 단지번호붙이기 - Python 풀이 (0) | 2022.04.01 |
[CODETREE Novice Mid] 시뮬레이션 2 / dx, dy 테크닉 / Quiz 빙빙 돌며 사각형 채우기 (0) | 2022.03.30 |
[CODETREE Novice Mid] 시뮬레이션 2 / dx, dy 테크닉 / Quiz 거울에 레이저 쏘기 (0) | 2022.03.30 |