[BaekJoon] 백준 21611번 마법사 상어와 블리자드
🎈문제
https://www.acmicpc.net/problem/21611
💬설명
- 복잡한 구현 문제.
- 푸는데 2시간 정도 걸렸다. 구현은 1시간 안에 했는데 자꾸 틀렸다고 나와서 히든 테케에서 틀린 부분 찾는데 1시간 걸렸다. 어쨋든 스스로 풀었으니까 일단 만족,,
- 놓친 부분은 다음과 같다.
- 각각 step을 수행할 때 arr가 빈값인 경우 예외 처리
- 연속하는 구슬의 개수를 세거나 구슬을 그룹별로 묶을 때 마지막에 세줘야 하는 것을 빼먹음
👩💻코드
N, M = map(int, input().split())
board = [[] for _ in range(N)]
for i in range(N):
board[i] = list(map(int, input().split()))
blizard = [[] for _ in range(M)]
for i in range(M):
blizard[i] = list(map(int, input().split()))
shark = [(N - 1) // 2, (N - 1) // 2]
result = [0, 0, 0]
def destroy(d, s):
global board, N, shark
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]
for i in range(1, s + 1):
nx = shark[0] + dx[d - 1] * i
ny = shark[1] + dy[d - 1] * i
# 격자를 넘어가면 continue
if nx < 0 or ny < 0 or nx >= N or ny >= N:
break
# 파괴
board[nx][ny] = 0
def board2list():
global board
arr = []
cur = shark[:]
dx = [0, 1, 0, -1]
dy = [-1, 0, 1, 0]
num = 1
direction = 0
is_over = False
while not is_over:
for i in range(2):
for j in range(num):
cur[0] += dx[direction]
cur[1] += dy[direction]
# 격자 밖으로 넘어간다면
if cur[0] < 0 or cur[1] < 0 or cur[0] >= N or cur[1] >= N:
is_over = True
break
# 회오리 순서대로 배열에 append
arr.append(board[cur[0]][cur[1]])
direction = (direction + 1) % 4
if is_over:
break
num += 1
return arr
def move(arr):
# 구슬 배열에서 빈칸 제거
return [arr[i] for i in range(len(arr)) if arr[i] != 0]
def explode(arr):
global result
# 구슬이 존재하지 않는 경우
if not arr:
return [], False
# 연속하는 구슬이 4개 이상이면 폭발
cur_marble = arr[0]
cur_num = 1
is_removed = False
for i in range(1, len(arr)):
# 같은 색의 구슬이라면
if arr[i] == cur_marble:
cur_num += 1
else:
# 다른 색의 구슬인데 4개 미만인 경우
if cur_num < 4:
cur_num = 1
cur_marble = arr[i]
# 다른 색의 구슬인데 4개 이상인 경우
else:
# 개수만큼 이전 구슬들 폭발
for j in range(1, cur_num + 1):
arr[i - j] = 0
# result에 폭발 개수 저장
result[cur_marble - 1] += cur_num
is_removed = True
# 새로운 색으로 update
cur_num = 1
cur_marble = arr[i]
# 마지막으로 현재 구슬들 체크
if cur_num >= 4:
is_removed = True
for j in range(1, cur_num + 1):
arr[len(arr) - j] = 0
result[cur_marble - 1] += cur_num
return arr, is_removed
def make_group(arr):
# 구슬이 존재하지 않는 경우
if not arr:
return []
# 그룹으로 묶어서 [구슬 개수, 구슬 번호]로 변경
new_arr = []
cur_type = arr[0]
cur_num = 1
for i in range(1, len(arr)):
# 같은 색의 구슬인 경우
if arr[i] == cur_type:
cur_num += 1
else:
# 다른 색의 구슬인 경우 그룹 [구슬 개수, 구슬 번호] 추가
new_arr.append(cur_num)
new_arr.append(cur_type)
cur_num = 1
cur_type = arr[i]
# 마지막 그룹 체크
new_arr.append(cur_num)
new_arr.append(cur_type)
return new_arr
def list2board(arr):
global N, shark
# list 를 회오리 모양 보드로 변경
new_board = [[0 for _ in range(N)] for _ in range(N)]
# 구슬이 없다면
if not arr:
return new_board
cur = shark[:]
dx = [0, 1, 0, -1]
dy = [-1, 0, 1, 0]
num = 1
direction = 0
cur_arr = 0
is_over = False
while not is_over:
for i in range(2):
for j in range(num):
cur[0] += dx[direction]
cur[1] += dy[direction]
# 격자 밖으로 넘어간다면
if cur[0] < 0 or cur[1] < 0 or cur[0] >= N or cur[1] >= N:
is_over = True
break
# 회오리 순서대로 보드에 append
new_board[cur[0]][cur[1]] = arr[cur_arr]
cur_arr += 1
# 구슬이 더이상 없다면
if cur_arr >= len(arr):
is_over = True
break
if is_over:
break
direction = (direction + 1) % 4
num += 1
return new_board
def solution():
global M, blizard, board, result
for i in range(M):
destroy(blizard[i][0], blizard[i][1]) # 방향, 거리
arr = board2list()
arr = move(arr)
while arr:
arr, is_removed = explode(arr)
if not is_removed:
break
arr = move(arr)
board = list2board(make_group(arr))
print(result[0] + 2 * result[1] + 3 * result[2])
solution()
728x90
반응형
'CS > Algorithm 문제' 카테고리의 다른 글
[BaekJoon] 백준 20058번 마법사 상어와 파이어스톰 (0) | 2021.10.21 |
---|---|
[BaekJoon] 백준 20057번 마법사 상어와 토네이도 (0) | 2021.10.20 |
[BaekJoon] 백준 21610번 마법사 상어와 비바라기 (0) | 2021.10.20 |
[BaekJoon] 백준 14889번 스타트와 링크 (0) | 2021.10.20 |
[BaekJoon] 백준 14888번 연산자 끼워넣기 (0) | 2021.10.19 |