문제 링크
코드트리 | 코딩테스트 준비를 위한 알고리즘 정석
국가대표가 만든 코딩 공부의 가이드북 코딩 왕초보부터 꿈의 직장 코테 합격까지, 국가대표가 엄선한 커리큘럼으로 준비해보세요.
www.codetree.ai
풀이
실수한 부분은 진 플레이어가 원래 가지고 있던 방향대로 이동하는 부분에서, 방향을 반대로 바꾼 플레이어는 바꾸기 전 방향으로 이동해 준 것이다. 방향을 바꾼 방향으로 이동해주어야 한다.
1. 한 칸 이동 함수
def move():
for i in range(1,m+1):
x,y,d,s = players[i]
board[x][y] = 0
nx = x + dx[d]
ny = y + dy[d]
nd = d
# 범위를 벗어나면 반대 방향으로 바꿔준다.
if nx < 0 or nx >= n or ny < 0 or ny >= n :
nd = (d+2) % 4
nx = x + dx[nd]
ny = y + dy[nd]
# 이동한 위치에 누가 있을 경우
if board[nx][ny] :
# 해당 위치에 있던 플레이어 정보
p2 = board[nx][ny]
x2,y2,d2,s2 = players[p2]
# 원래 있던 플레이어가 이긴 경우
if s2 + guns[p2] > s + guns[i]:
# 포인트 계산
point[p2] += (s2 + guns[p2]) - (s + guns[i])
# 진 플레이어가 총을 가지고 있다면 자리에 내려둔다
if guns[i]:
graph[nx][ny].append(guns[i])
guns[i] = 0
# 진 플레이어 한 칸 이동
back(i,nx,ny,nd,s)
# 이긴 플레이어 총 갱신
get_gun(p2, nx, ny)
# 점수가 같을 경우
elif s2 + guns[p2] == s + guns[i] :
# 원래 있던 플레이어가 이긴 경우
if s2 > s :
# 진 플레이어가 총을 가지고 있다면 자리에 내려둔다
if guns[i]:
graph[nx][ny].append(guns[i])
guns[i] = 0
# 진 플레이어 한 칸 이동
back(i,x2,y2,nd,s)
# 이긴 플레이어 총 갱신
get_gun(p2, nx, ny)
# 새로 온 플레이어가 이긴 경우
else :
# 진 플레이어가 총을 가지고 있다면 자리에 내려둔다
if guns[p2]:
graph[nx][ny].append(guns[p2])
guns[p2] = 0
# 진 플레이어 한 칸 이동
back(p2,nx,ny,d2,s2)
# 새로 이동한 플레이어 위치 갱신
board[nx][ny] = i
players[i] = [nx,ny,nd,s]
# 이긴 플레이어 총 갱신
get_gun(i, nx, ny)
else :
# 포인트 계산
point[i] += (s + guns[i]) - (s2 + guns[p2])
# 진 플레이어가 총을 가지고 있다면 자리에 내려둔다
if guns[p2]:
graph[nx][ny].append(guns[p2])
guns[p2] = 0
# 진 플레이어 한 칸 이동
back(p2,x2,y2,d2,s2)
# 새로 이동한 플레이어 위치 갱신
board[nx][ny] = i
players[i] = [nx,ny,nd,s]
# 이긴 플레이어 총 갱신
get_gun(i, nx, ny)
# 이동한 위치에 누가 없을 경우
else :
# 총이 있으면 가장 센 총을 얻는다
if len(graph[nx][ny]):
if max(graph[nx][ny]) > guns[i]:
tmp = max(graph[nx][ny])
graph[nx][ny].remove(tmp)
# 원래 가지고 있던 총이 있다면 자리에 내려둔다
if guns[i]:
graph[nx][ny].append(guns[i])
guns[i] = tmp
# 이동한 플레이어 위치 갱신
board[nx][ny] = i
players[i] = [nx,ny,nd,s]
2. 진 플레이어 이동 함수
def back(num, x,y,d,s):
for i in range(4):
nx = x + dx[d]
ny = y + dy[d]
# 범위 벗어나면 오른쪽으로 회전
if nx < 0 or nx >= n or ny < 0 or ny >= n:
d = (d+1) % 4
continue
# 다른 플레이어가 있으면 오른쪽으로 회전
if board[nx][ny] :
d = (d+1) % 4
continue
board[nx][ny] = num
players[num] = [nx,ny,d,s]
# 이동한 위치에 총이 있으면 가장 센 총 얻는다
if len(graph[nx][ny]) > 0 :
tmp = max(graph[nx][ny])
graph[nx][ny].remove(tmp)
guns[num] = tmp
break
3. 이긴 플레이어 총 갱신 함수
def get_gun(num, x,y):
# 해당 위치에 총이 없다면
if len(graph[x][y]) == 0 :
return
# 현재 가지고 있는 총이 더 세다면
if guns[num] > max(graph[x][y]) :
return
# 가장 센 총으로 교환
tmp = max(graph[x][y])
graph[x][y].remove(tmp)
if guns[num]:
graph[x][y].append(guns[num])
guns[num] = tmp
전체 코드는 다음과 같다.
각 배열 별 역할은 아래와 같다.
graph : 위치별 총의 공격력을 저장
guns : index에 해당하는 플레이어가 가지고 있는 총의 공격력 저장
players : index에 해당하는 플레이어의 현재 위치, 방향, 초기 공격력 저장
point : index에 해당하는 플레이어의 얻은 포인트 저장
n,m,k = map(int,input().split())
graph = [ [[] for _ in range(n)] for _ in range(n)]
for i in range(n):
tmp = list(map(int,input().split()))
for j in range(n):
if tmp[j] :
graph[i][j].append(tmp[j])
dx = [-1,0,1,0]
dy = [0,1,0,-1]
players = [ [] for _ in range(m+1)]
board = [ [0] * n for _ in range(n) ]
for i in range(1,m+1):
x,y,d,s = map(int,input().split())
x-=1
y-=1
players[i] = [x,y,d,s]
board[x][y] = i
guns = [0] * (m+1)
point = [0] * (m+1)
def back(num, x,y,d,s):
for i in range(4):
nx = x + dx[d]
ny = y + dy[d]
if nx < 0 or nx >= n or ny < 0 or ny >= n:
d = (d+1) % 4
continue
if board[nx][ny] :
d = (d+1) % 4
continue
board[nx][ny] = num
players[num] = [nx,ny,d,s]
if len(graph[nx][ny]) > 0 :
tmp = max(graph[nx][ny])
graph[nx][ny].remove(tmp)
guns[num] = tmp
break
def get_gun(num, x,y):
if len(graph[x][y]) == 0 :
return
if guns[num] > max(graph[x][y]) :
return
tmp = max(graph[x][y])
graph[x][y].remove(tmp)
if guns[num]:
graph[x][y].append(guns[num])
guns[num] = tmp
def move():
for i in range(1,m+1):
x,y,d,s = players[i]
board[x][y] = 0
nx = x + dx[d]
ny = y + dy[d]
nd = d
if nx < 0 or nx >= n or ny < 0 or ny >= n :
nd = (d+2) % 4
nx = x + dx[nd]
ny = y + dy[nd]
# 이동한 위치에 누가 있음
if board[nx][ny] :
p2 = board[nx][ny]
x2,y2,d2,s2 = players[p2]
# 원래 있던 애가 이김
if s2 + guns[p2] > s + guns[i]:
point[p2] += (s2 + guns[p2]) - (s + guns[i])
if guns[i]:
graph[nx][ny].append(guns[i])
guns[i] = 0
back(i,nx,ny,nd,s)
get_gun(p2, nx, ny)
elif s2 + guns[p2] == s + guns[i] :
# 원래 있던 애가 이김
if s2 > s :
if guns[i]:
graph[nx][ny].append(guns[i])
guns[i] = 0
back(i,x2,y2,nd,s)
get_gun(p2, nx, ny)
# 새로 온 애가 이김
else :
if guns[p2]:
graph[nx][ny].append(guns[p2])
guns[p2] = 0
back(p2,nx,ny,d2,s2)
board[nx][ny] = i
players[i] = [nx,ny,nd,s]
get_gun(i, nx, ny)
else :
point[i] += (s + guns[i]) - (s2 + guns[p2])
if guns[p2]:
graph[nx][ny].append(guns[p2])
guns[p2] = 0
back(p2,x2,y2,d2,s2)
board[nx][ny] = i
players[i] = [nx,ny,nd,s]
get_gun(i, nx, ny)
# 이동한 위치에 누가 없음
else :
# 총이 있으면
if len(graph[nx][ny]):
if max(graph[nx][ny]) > guns[i]:
tmp = max(graph[nx][ny])
graph[nx][ny].remove(tmp)
if guns[i]:
graph[nx][ny].append(guns[i])
guns[i] = tmp
board[nx][ny] = i
players[i] = [nx,ny,nd,s]
for _ in range(k):
move()
print(*point[1:])
'개발 > algorithm' 카테고리의 다른 글
[코드트리] 산타의 선물 공장 - Python (1) | 2023.10.11 |
---|---|
[코드트리] 포탑 부수기 - Python (2) | 2023.10.11 |
[코드트리] 코드트리 빵 - Python (1) | 2023.10.11 |
[프로그래머스][level1] 달리기 경주 - python (0) | 2023.08.02 |
[Python] 반올림 처리하기 - 오사오입 (0) | 2023.03.05 |