[BOJ]16946. 벽 부수고 이동하기 4
❌code 1
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import sys
from collections import deque
def bfs(r, c):
dr = [-1, 1, 0, 0] # 상하좌우
dc = [0, 0, -1, 1] # 상하좌우
q = deque()
q.append([r, c]) # 시작 지점 추가
walls = set() # 주위 벽의 좌표 저장
cnt = 1 # 이동할 수 있는 칸의 개수
while q:
now_r, now_c = q.popleft()
for d in range(4):
nr, nc = now_r + dr[d], now_c + dc[d]
if nr < 0 or R <= nr or nc < 0 or C <= nc:
continue
if visited[nr][nc]:
continue
# 벽을 만난 경우 벽의 좌표를 저장
if matrix[nr][nc]:
walls.add((nr, nc))
continue
visited[nr][nc] = 1
cnt += 1
q.append([nr, nc])
# 만난 모든 벽에 대하여 이동 가능한 칸의 개수를 추가
for wall_r, wall_c in list(walls):
matrix[wall_r][wall_c] += cnt
matrix[wall_r][wall_c] = matrix[wall_r][wall_c] % 10
R, C = map(int, input().split())
matrix = [list(map(int, sys.stdin.readline().rstrip())) for _ in range(R)]
visited = [[0] * C for _ in range(R)] # 이동한 지점을 표시
for row in range(R):
for col in range(C):
if matrix[row][col] == 0 and visited[row][col] == 0:
visited[row][col] = 1 # 출발 지점 표시
bfs(row, col)
for row in range(R):
print(''.join(map(str, matrix[row])))
시도
원하는 값을 matrix
에 저장하여 이를 출력한다. 이때 벽인 곳은 이동할 수 있는 칸의 개수를 10으로 나눈 나머지를 출력한다.
이를 위해 벽의 좌표에 이동 가능한 칸의 개수를 추가하며 계속 10으로 나눈 나머지를 갱신해 주었다.
1
2
3
4
# 만난 모든 벽에 대하여 이동 가능한 칸의 개수를 추가
for wall_r, wall_c in list(walls):
matrix[wall_r][wall_c] += cnt
matrix[wall_r][wall_c] = matrix[wall_r][wall_c] % 10
문제
틀린 결과 반환
⭕code 2
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import sys
from collections import deque
def bfs(r, c):
dr = [-1, 1, 0, 0] # 상하좌우
dc = [0, 0, -1, 1] # 상하좌우
q = deque()
q.append([r, c]) # 시작 지점 추가
walls = set() # 주위 벽의 좌표 저장
cnt = 1 # 이동할 수 있는 칸의 개수
while q:
now_r, now_c = q.popleft()
for d in range(4):
nr, nc = now_r + dr[d], now_c + dc[d]
if nr < 0 or R <= nr or nc < 0 or C <= nc:
continue
if visited[nr][nc]:
continue
# 벽을 만난 경우 벽의 좌표를 저장
if matrix[nr][nc]:
walls.add((nr, nc))
continue
visited[nr][nc] = 1
cnt += 1
q.append([nr, nc])
# 만난 모든 벽에 대하여 이동 가능한 칸의 개수를 추가
for wall_r, wall_c in list(walls):
matrix[wall_r][wall_c] += cnt
R, C = map(int, input().split())
matrix = [list(map(int, sys.stdin.readline().rstrip())) for _ in range(R)]
visited = [[0] * C for _ in range(R)] # 이동한 지점을 표시
for row in range(R):
for col in range(C):
if matrix[row][col] == 0 and visited[row][col] == 0:
visited[row][col] = 1 # 출발 지점 표시
bfs(row, col)
for row in range(R):
for col in range(C):
print(matrix[row][col] % 10, end='')
print()
시도
틀릴만한 부분이 보이지 않아 이동할 수 있는 칸의 개수를 계속 10의 나머지로 갱신하는 대신 출력 과정을 수정하여 통과하였다.
어차피 (x + y + z + ...) % 10
의 계산을 하나 (x % 10) + (y % 10) + (z % 10) + ...
의 계산을 하나 동일하리라 생각했는데 아래 반례에서 문제를 발견하였다.
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
8 20
11010100001101010000
01110101010101010101
01110010101010010010
00100101000010010101
01101101100101010110
00000001000010101010
01101101101011101010
00000000000101010110
# code 1의 결과
04030000000000000000
00600000000000000900
00800000000000000000
00000000000000000108
00000000000000000170
00000000000000001070
00000000000000202070
00000000000000030450
# code 2의 결과
02010600008300080000
00200608070300080102
00100070701090080030
00000001000080080207
00000000000100000360
00000000000020105070
00000000000012406070
00000000000103050450
문제 해결
결과적으로 나눗셈에 문제가 있는 것은 아니었다. code 1
의 경우 matrix[wall_r][wall_c]
의 값이 10의 배수가 나온다면 그 값은 0
으로 저장될 것이다. 여기서 문제가 생기는데, 이후 다시 while loop가 진행될 때에 0
으로 표시된 부분은 아래 코드를 실행할 수 없다. 따라서 틀린 결과를 반환하게 된다.
1
2
3
4
5
# 벽을 만난 경우 벽의 좌표를 저장
if matrix[nr][nc]:
walls.add((nr, nc))
continue
요약
양의 정수를 벽으로 판별하는 코드에서 벽으로 저장된 값을 10의 나머지로 갱신할 시 해당 값은 양의 정수를 벗어난 값 즉, 0
을 가질 수 있게 된다. 따라서 양의 정수 값은 벽이라는 가정이 깨지게 되어 오류가 발생하게 된다.
This post is licensed under CC BY 4.0 by the author.