삼성 기출 상어시리즈 첫 발,,
마법사 상어가 N*N 크기의 격자에서 파이어볼 M개를 이동시킨다. 파이어볼 i는 초기에 의 위치에서 질량 , 방향 , 속력 을 가지고 이는 입력으로 주어진다. 상어가 이동명령을 내리면
이렇게 이동명령의 순서가 주어질때 k번의 명령 뒤 남은 파이어볼 질량의 총 합은?
시키는 대로 하면 되는 시뮬레이션 문젠데,, 디버깅에서 한참 헤멨다 ^_ㅜ 이런 문제는 코드로 우선 적기보다 설계를 똑바로 작성하고 문제푸는 습관을 들여야 할듯 ,,,
- board[i][j] : (i,j)의 위치에 있는 파이어볼 정보를 담는 리스트
for i in range(M):
r, c, m, s, d = map(int, input().split())
board[r-1][c-1].append([m, s, d, -1])
1 ≤ ri, ci ≤ N이므로 r-1, c-1 처리 해줘야됨 ,,
# 1. 모든 파이어볼에 대해서 방향 d로 s만큼 이동하기
for i in range(N):
for j in range(N):
for f in range(len(board[i][j])):
fireball = board[i][j].pop(0)
nx, ny = i, j
m, s, d, moves = fireball
if moves != move:
nx, ny = move_fireball(i, j, m, s, d)
board[nx][ny].append([m, s, d, move])
move_fireball함수를 이용해서 각각의 파이어볼을 이동한 결과를 계산하고, 전체 격자에서 이 정보를 갱신해준다.
이동을 구현한 함수는 다음과 같다.
def move_fireball(x, y, m, s, d):
# d방향으로 s만큼 이동시키기 (m, s, d)
nx, ny = (x+dx[d]*s)%N, (y+dy[d]*s)%N
return nx, ny
격자의 행과 열은 1번부터 N번까지 번호가 매겨져 있고, 1번 행은 N번과 연결되어 있고, 1번 열은 N번 열과 연결되어 있다.
라고 주어졌기 때문에, 원래 좌표+방향 d로 s만큼 이동한 값을 N으로 나눈 나머지가 좌표가 된다.
# 2. 이동 후 한칸에 2개이상 존재하는지
for i in range(N):
for j in range(N):
if len(board[i][j]) > 1:
length = len(board[i][j])
# 2개 이상이면
sumM, sumS, oddcount, evencount = 0, 0, 0, 0
for f in board[i][j]:
sumM += f[0]
sumS += f[1]
if f[2] % 2 == 0:
evencount += 1
else:
oddcount += 1
# 나눈 뒤 질량이 0보다 크면 4개로 나누기
if sumM // 5 != 0:
m, s = sumM//5, sumS//length
if oddcount == 0 or evencount == 0:
# 전부 홀수거나 짝수면
board[i][j] = [[m,s,0,move], [m,s,2,move], [m,s,4,move], [m,s,6,move]]
else:
board[i][j] = [[m,s,1,move], [m,s,3,move], [m,s,5,move], [m,s,7,move]]
# 아니면 전체 소멸
else:
board[i][j] = []
모든 격자를 돌며 칸에 파이어볼이 2개 이상이면 주어진대로 처리해준다. 해당 칸의 모든 파이어볼의 방향이 홀/짝인지 확인하는 부분은 oddcount와 evencount를 이용해서 구현했다. oddcount 또는 evencount가 해당 칸의 파이어볼 개수와 같으면 조건을 만족한다는 의미니까 방향을 0,2,4,6으로, 아니면 1,3,5,7로 append해줬다.
전체 코드는 다음과 같다.
import sys
input = sys.stdin.readline
N, M, K = map(int, input().split())
board = [[[] for _ in range(N)] for _ in range(N)]
dx = [-1, -1, 0, 1, 1, 1, 0, -1]
dy = [0, 1, 1, 1, 0, -1, -1, -1]
def move_fireball(x, y, m, s, d):
# d방향으로 s만큼 이동시키기 (m, s, d)
nx, ny = (x+dx[d]*s)%N, (y+dy[d]*s)%N
return nx, ny
for i in range(M):
r, c, m, s, d = map(int, input().split())
board[r-1][c-1].append([m, s, d, -1])
for move in range(K):
# 1. 모든 파이어볼에 대해서 방향 d로 s만큼 이동하기
for i in range(N):
for j in range(N):
for f in range(len(board[i][j])):
fireball = board[i][j].pop(0)
nx, ny = i, j
m, s, d, moves = fireball
if moves != move:
nx, ny = move_fireball(i, j, m, s, d)
board[nx][ny].append([m, s, d, move])
# 2. 이동 후 한칸에 2개이상 존재하는지
for i in range(N):
for j in range(N):
if len(board[i][j]) > 1:
length = len(board[i][j])
# 2개 이상이면
sumM, sumS, oddcount, evencount = 0, 0, 0, 0
for f in board[i][j]:
sumM += f[0]
sumS += f[1]
if f[2] % 2 == 0:
evencount += 1
else:
oddcount += 1
# 나눈 뒤 질량이 0보다 크면 4개로 나누기
if sumM // 5 != 0:
m, s = sumM//5, sumS//length
if oddcount == 0 or evencount == 0:
# 전부 홀수거나 짝수면
board[i][j] = [[m,s,0,move], [m,s,2,move], [m,s,4,move], [m,s,6,move]]
else:
board[i][j] = [[m,s,1,move], [m,s,3,move], [m,s,5,move], [m,s,7,move]]
# 아니면 전체 소멸
else:
board[i][j] = []
answer = 0
for i in range(N):
for j in range(N):
for f in board[i][j]:
answer += f[0]
print(answer)
흐름이 긴 구현문제는 쉽지 않구만요,,