Coding Test/Python
[백준] 14890번: 경사로 (골드3, 파이썬)
lim.dev
2023. 12. 30. 18:19
https://www.acmicpc.net/problem/14890
14890번: 경사로
첫째 줄에 N (2 ≤ N ≤ 100)과 L (1 ≤ L ≤ N)이 주어진다. 둘째 줄부터 N개의 줄에 지도가 주어진다. 각 칸의 높이는 10보다 작거나 같은 자연수이다.
www.acmicpc.net
아이디어
문제를 보고 요구사항을 그대로 구현하였다.
우선 길을 가로로 탐색하는 메서드를 작성하였다.
check 메서드
우선 크게 세 가지 경우로 나누었다.
- 현재 칸이 다음 칸 보다 1만큼 높을 때
- 현재 칸이 다음 칸 보다 1만큼 낮을 때
- 현재 칸과 다음 칸이 2 이상 차이가 날 때
위 세가지 경우 중 3번째는 그냥 break 하면 된다.
첫 번째 경우와 두 번째 경우는 각각 낮은 칸을 기준으로 L(경사로의 길이)만큼 검사해주었다.
전체 순서는 이렇다.
- i 값을 증가한다. (N만큼 반복)
- i번째 라인을 검사하기 위한 line 변수를 초기화해준다. (line = True)
- j 값을 증가한다. (N만큼 반복)
- 현재 칸(maps[i][j])이 다음 칸(maps[i][j+1]) 보다 1만큼 높을 때
- visited[i][j+1]이 0이면 1로 만들어준다.
- visited[i][j+1]이 1이면 line을 False로 변경해주고 break한다. (경사로가 이미 설치되어 있다는 뜻이므로)
- 경사로의 길이(L) 만큼 오른쪽 요소들을 검사한다.
- 만약 길이가 다른 요소가 있으면 line을 False로 변경해주고 break한다.
- 현재 칸(maps[i][j])이 다음 칸(maps[i][j+1]) 보다 1만큼 낮을 때
- visited[i][j]이 0이면 1로 만들어준다.
- visited[i][j]이 1이면 line을 False로 변경해주고 break한다. (경사로가 이미 설치되어 있다는 뜻이므로)
- 경사로의 길이(L) 만큼 오른쪽 요소들을 검사한다.
- 만약 길이가 다른 요소가 있으면 line을 False로 변경해주고 break한다.
- 현재 칸(maps[i][j])과 다음 칸(maps[i][j+1])이 2 이상 차이가 날 때
- line을 False로 변경해주고 break한다.
- 3~6번을 N-1만큼 반복 한 후 line이 True 라면 count를 1 증가시킨다.
- 1~7을 반복한다.
단순 구현이지만 이 순서도를 떠올리고 구현하는데 1시간이나 걸렸다...
가로 세로 검사
가로만 검사하는 메서드를 만들었으니 세로도 검사해야 한다.
필자는 maps를 왼쪽으로 90도 돌린 후 메서드를 재사용하기로 했다.
rmaps = [[0 for _ in range(N)] for _ in range(N)]
for i in range(N): # 왼쪽으로 90도 회전
for j in range(N):
rmaps[i][j] = maps[j][N-(i+1)]
전체 코드
count = 0
def check(maps):
global count
for i in range(N):
line = True
for j in range(N-1):
if line == False:
break
if maps[i][j] - maps[i][j+1] == 1: # 현재 칸이 다음 칸 보다 1 높으면
if visited[i][j+1] == 0: visited[i][j+1] = 1
else:
line = False
break
tmp_j = j+1
for k in range(L - 1):
tmp_j += 1
if 0 <= tmp_j < N and maps[i][j+1] == maps[i][tmp_j] and visited[i][tmp_j] == 0:
visited[i][tmp_j] = 1
continue
line = False
break
elif maps[i][j] - maps[i][j+1] == -1: # 현재 칸이 다음 칸 보다 1 낮으면
if visited[i][j] == 0: visited[i][j] = 1
else:
line = False
break
tmp_j = j
visited[i][j] = 1
for k in range(L - 1):
tmp_j -= 1
if 0 <= tmp_j < N and maps[i][j] == maps[i][tmp_j]and visited[i][tmp_j] == 0:
visited[i][tmp_j] = 1
continue
line = False
break
elif abs(maps[i][j] - maps[i][j+1]) >= 2: line = False # 현재 칸과 다음 칸이 2이상 차이나면
if line == True:
count += 1
N, L = map(int, input().split())
visited = [[0 for _ in range(N)] for _ in range(N)]
maps = [[int(x) for x in input().split()] for _ in range(N)]
check(maps)
visited = [[0 for _ in range(N)] for _ in range(N)]
rmaps = [[0 for _ in range(N)] for _ in range(N)]
for i in range(N): # 왼쪽으로 90도 회전
for j in range(N):
rmaps[i][j] = maps[j][N-(i+1)]
check(rmaps)
print(count)