BOJ_17143_낚시왕
상어의 이동과 낚시 로직을 구현하는 구현 문제
다른 건 다 무난하지만, 상어의 이동을 계산하는 부분이 까다롭다
1초 당 움직일 수 있는 거리가 주어지는데, 만약 그만큼 이동을 하다 벽을 만나면 방향을 전환해서 남은 칸만큼 돌아와야 한다
물론 ==이동할 칸 % 2 x (길이 - 1)==를 한 뒤에 while 문으로 상어를 이동시키며 벽을 확인해도 되지만,
이왕 반복문 안 쓰기로 한 거 계산식으로 풀어보기로 했다
그렇지만 결국 내 머리로 안 돼서 계산으로 푸는 여러 답들을 참고해봤고(집단 지성^^) 내가 이해한 로직은 아래와 같다
상어 이동 로직
-
싸이클을 구한다
상어가 현재 자리에 같은 방향으로 돌아오기 위해서는 2 x (범위 - 1)의 싸이클을 갖는다
그렇기 때문에 (현재 좌표 + 방향 d x 가는 거리 s)를 싸이클로 나눈 나머지를 구해서 나머지만 가지고 계산하면 된다 -
여기서 구한 나머지(편의 상 r이라고 하겠다)는 이제 두 가지 조건에 따라 처리한다
- 0 <= r < 범위 라면 r은 좌표와 동일하다. 벽에 부딪히지 않은 상태인 것이다
- 범위 <= r < 싸이클 이라면 벽에 부딪혀 방향 전환을 해야한다
이때, 싸이클 - 현재 거리를 하면 방향 전환 후 도착하는 지점이 나온다
길이가 5이고, 싸이클이 2 x (5 - 1) = 8의 길이인 경우를 생각해보자
어떤 값을 싸이클로 나눈 나머지의 범위는 0 <= x < 8이 될 것이다
거리 | 좌표 |
---|---|
0 | 0 |
1 | 1 |
2 | 2 |
3 | 3 |
4 | 4 |
5 | 3 |
6 | 2 |
7 | 1 |
상어가 벽에 부딪히고, 즉 최대 가능 길이인 5 - 1 = 4에 도달한 후, 다시 1씩 작아지며 이동하는데 | |
이때 이동하는 거리는 (4 + n) 이고 좌표는 ==(4 - n)==로 4를 기준으로 대칭된다. |
그렇기 때문에 둘을 더한 값은 싸이클의 길이가 되며
싸이클 - 현재 거리를 하면 1회 방향 전환 후 도달하게 되는 좌표가 나오는 것이다
이를 활용해서 상어를 이동시켜 주면 된다
그러나 나는 수학과가 아니기 때문에 틀렸을 수도 있다 지적 환영~~
R, C, M = list(map(int, input().split()))
fish_bowl = [[0] * (C) for _ in range(R)]
shark_dic = {}
shark_sum = 0
dx = [0, -1, 1, 0, 0]
dy = [0, 0, 0, 1, -1]
def input_data():
# 입력
for i in range(M):
temp_li = list(map(int, input().split()))
temp_li[0] -= 1
temp_li[1] -= 1
shark_dic[i + 1] = temp_li # x, y, 속력, 이동 방향, 크기
fish_bowl[temp_li[0]][temp_li[1]] = i + 1 # 상어 표시
def print_fish():
for i in range(R):
for j in range(C):
print(fish_bowl[i][j], end=" ")
print('')
print('')
def move_right(i):
# 낚시왕의 이동
for j in range(R):
if fish_bowl[j][i] > 0:
shark_info = shark_dic.pop(fish_bowl[j][i])
fish_bowl[j][i] = 0
return shark_info[4]
return 0
def calculate(s, nx, ny, now_d):
cycle_x = 2 * (R - 1)
cycle_y = 2 * (C - 1)
if now_d in [3, 4]: # 좌우 이동
ny = (ny + s * dy[now_d]) % cycle_y
if ny >= C:
ny = cycle_y - ny
now_d = 7 - now_d # 3 <-> 4 방향 전환
elif now_d in [1, 2]: # 상하 이동
nx = (nx + s * dx[now_d]) % cycle_x
if nx >= R:
nx = cycle_x - nx
now_d = 3 - now_d # 1 <-> 2 방향 전환
return nx, ny, now_d
def move_shark():
for key in shark_dic.keys():
x, y, s, d, z = shark_dic[key]
next_d = d + 1 if d % 2 == 1 else d - 1
length = R if d <= 2 else C
nx, ny, direction = calculate(s, x, y, d)
shark_dic[key] = [nx, ny, s, direction, z]
def shark_position():
global fish_bowl
fish_bowl = [[0] * (C) for _ in range(R)]
remove_key = []
for key in shark_dic.keys():
x, y, s, d, z = shark_dic[key]
if fish_bowl[x][y] == 0:
fish_bowl[x][y] = key
else:
rival_shark = shark_dic[fish_bowl[x][y]]
if rival_shark[4] > z:
remove_key.append(key)
else:
remove_key.append(fish_bowl[x][y])
fish_bowl[x][y] = key
for key in remove_key:
shark_dic.pop(key)
# 실행
input_data()
if M == 0:
print(0)
else:
for i in range(0, C):
# 낚시
shark_sum += move_right(i)
# 상어 이동
move_shark()
# 상어 배치
shark_position()
print(shark_sum)