반응형
1. 문제 - 백준 마법사 상어와 파이어볼 (삼성 SW 역량테스트 기출)
https://www.acmicpc.net/problem/20056
✅ 풀이
- 파이어볼의 이동을 'infos'라는 배열로 두고 각 상태별로 파이어볼의 좌표, 질량, 방향 등을 저장한다.
- 또한 이동하기 전에 remove를 통해 비워준다.
N, M, K = map(int, input().split()) # n: 격자크기 m: 파이어볼 갯수, k: 명령한 횟수
dx = [-1, -1, 0, 1, 1, 1, 0, -1] # 사진의 0 ~ 8의 방향대로 이동할 offset 배열
dy = [0, 1, 1, 1, 0, -1, -1, -1]
board = [[[] for _ in range(N)] for _ in range(N)]
infos = [] # 파이어볼의 정보를 담을 배열
answer = 0
for _ in range(M):
r, c, m, s, d = map(int, input().split())
infos.append([r-1, c-1, m, d, s])
board[r-1][c-1].append([m, d, s])
def move():
for x, y, m, d, s in infos:
nx = (x + dx[d] * s) % N # d의 방향대로 s만큼 이동
ny = (y + dy[d] * s) % N # N으로 나누는 이유는 1행과 1열은 각각 N행, N열과 연결되어있기 때문이다.
board[nx][ny].append([m, d, s])
board[x][y].remove([m, d, s]) # 이동하면서 그 전에 있던 파이어볼들 비움처리 해주어야함
for _ in range(K): # K회 만큼 명령
move() # 파이어볼 움직이기
for x in range(N): # 파이어볼 나누는 과정
for y in range(N):
if len(board[x][y]) >= 2: # 2개 이상의 파이어볼이 들어있을 경우,
_len = len(board[x][y])
m = 0 # 질량의 합
s = 0 # 속력의 합
even_count, odd_count = 0, 0
for M, D, S in board[x][y]:
m += M
s += S
if D%2 == 0:
even_count += 1
else:
odd_count += 1
m //= 5
s //= _len
if m > 0:
if even_count == _len or odd_count == _len: # 모든 파이어볼의 방향이 짝수 혹은 홀수라면
board[x][y] = [[m, 0, s], [m, 2, s], [m, 4, s], [m, 6, s]]
else:
board[x][y] = [[m, 1, s], [m, 3, s], [m, 5, s], [m, 7, s]]
else: # 질량이 0이라면 파이어볼이 사라지므로 빈 배열로 둔다.
board[x][y] = []
infos = []
for x in range(N):
for y in range(N):
if board[x][y]:
for m, d, s in board[x][y]:
infos.append([x, y, m, d, s]) # 현재 상태의 파이어볼 배열 정보를 새롭게 저장해준다.
for x in range(N):
for y in range(N):
if board[x][y]:
for m, _, _ in board[x][y]:
answer += m
print(answer)
✅ 다른 풀이
- 파이어볼을 이동하는 방식 외에 모두 동일하다.
- 아래 풀이에서는 파이어볼의 이동을 먼저 배열을 비우고 (pop) -> 새로운 위치를 추가(append) 하는 방식으로 풀이한다.
N, M, K = map(int, input().split()) # n: 격자크기 m: 파이어볼 갯수, k: 명령한 횟수
dx = [-1, -1, 0, 1, 1, 1, 0, -1] # 사진의 0 ~ 8의 방향대로 이동할 offset 배열
dy = [0, 1, 1, 1, 0, -1, -1, -1]
board = [[[] for _ in range(N)] for _ in range(N)]
infos = [] # 파이어볼의 정보를 담을 배열
answer = 0
for _ in range(M):
r, c, m, s, d = map(int, input().split())
infos.append([r-1, c-1, m, d, s])
def move():
while infos:
x, y, m, d, s = infos.pop()
nx = (x + dx[d] * s) % N # d의 방향대로 s만큼 이동
ny = (y + dy[d] * s) % N # N으로 나누는 이유는 1행과 1열은 각각 N행, N열과 연결되어있기 때문이다.
board[nx][ny].append([m, d, s])
for _ in range(K): # K회 만큼 명령
move() # 파이어볼 움직이기
for x in range(N): # 파이어볼 나누는 과정
for y in range(N):
if len(board[x][y]) >= 2: # 2개 이상의 파이어볼이 들어있을 경우,
_len = len(board[x][y])
m = 0 # 질량의 합
s = 0 # 속력의 합
even_count, odd_count = 0, 0
while board[x][y]:
M, D, S = board[x][y].pop()
m += M
s += S
if D%2 == 0:
even_count += 1
else:
odd_count += 1
m //= 5
s //= _len
if m > 0:
if even_count == _len or odd_count == _len: # 모든 파이어볼의 방향이 짝수 혹은 홀수라면
infos.extend([[x, y, m, 0, s], [x, y, m, 2, s], [x, y, m, 4, s], [x, y, m, 6, s]])
else:
infos.extend([[x, y, m, 1, s], [x, y, m, 3, s], [x, y, m, 5, s], [x, y, m, 7, s]])
if len(board[x][y]) == 1:
infos.append([x, y] + board[x][y].pop())
print(sum([f[2] for f in infos]))
반응형
'⚙️ 알고리즘 > 문제풀이' 카테고리의 다른 글
[Python] 프로그래머스 석유 시추, 백준 16235 나무 재테크 (0) | 2025.07.26 |
---|---|
[Python] 백준 1339 단어수학, 백준 20055 컨베이어 벨트 위의 로봇 (0) | 2025.07.24 |
[Python] 백준 미세먼지 안녕! (0) | 2025.07.10 |
[Python] 백준 아기상어 (0) | 2025.07.09 |
[Python] 프로그래머스 숫자게임, 백준 청소년 상어 (0) | 2025.07.09 |