문제종류
구현, dx dy technique
풀이시간
설계 20분 구현 70분
풀이방법
해당 문제는 격자에서의 총의 정보를 갱신하는 로직과 사람과 사람 사이의 배틀로직을 요구사항대로 구현하면 되는 문제이다.
격자에 총은 2개 이상이 존재할 수 있다는 점을 주의하며 풀어야 한다.
코드
# 위 오 아 왼
dx, dy = [-1, 0, 1, 0], [0, 1, 0, -1]
def in_range(x, y, n):
return 1 <= x <= n and 1 <= y <= n
def is_in_person(x, y, parr):
for p in parr:
px, py, *_ = p
if (x, y) == (px, py):
return True
return False
def main():
n, m, k = map(int, input().split())
arr = [[0] + list(map(int, input().split())) for i in range(n)]
arr = [[0] * (n + 1)] + arr
gun_info = {}
# 총 정보 초기화
for i in range(1, n + 1):
for j in range(1, n + 1):
gun_info[(i, j)] = []
if arr[i][j] != 0:
gun_info[(i, j)].append(arr[i][j])
# 사람 정보 x,y,d,s,att,cnt
parr = []
for i in range(m):
# 좌 방향 능력치
x, y, d, s = map(int, input().split())
parr.append([x, y, d, s, 0, 0])
for _ in range(k):
for pi in range(len(parr)):
# 좌표, 방향, 초기능력치, 공격력, 총점수
px, py, pd, ps, pa, pc = parr[pi]
# 이동 격자 벗어날때 방향전환 d=d^2
nx, ny = px + dx[pd], py + dy[pd]
if not in_range(nx, ny, n):
pd = pd ^ 2
nx, ny = px + dx[pd], py + dy[pd]
# 우선 이동
parr[pi] = [nx, ny, pd, ps, pa, pc]
is_next_p = -1
# 플레이어가 있는지 체크
for pii in range(len(parr)):
if pii == pi:
continue
ppx, ppy, *_ = parr[pii]
if (ppx, ppy) == (nx, ny):
is_next_p = pii
# 플레이어가 없을 경우
if is_next_p == -1:
# 해당 칸에 총이 있을 경우
if len(gun_info[(nx, ny)]) != 0:
# 총의 가장 큰 값이 본인 총보다 클경우
if gun_info[(nx, ny)][-1] > pa:
bpa = pa
pa = gun_info[(nx, ny)][-1]
# 총 한칸 감소
gun_info[(nx, ny)].pop()
# 총을 가지고 있었을때 내림
if bpa != 0:
gun_info[(nx, ny)].append(bpa)
# 오름차순 정렬
gun_info[(nx, ny)].sort()
parr[pi] = [nx, ny, pd, ps, pa, pc]
# 플레이어가 있을 경우
else:
npx, npy, npd, nps, npa, npc = parr[is_next_p]
# 능력치 + 공격력, 능력치, 인덱스
tmp: list[tuple] = [(npa + nps, nps, is_next_p), (pa + ps, ps, pi)]
tmp.sort(key=lambda xx: (-xx[0], -xx[1]))
winner = tmp[0]
loser = tmp[1]
# 총 합차이 만큼 (이긴 사람 점수 획득)
wi = winner[2]
winner_append_point = (tmp[0][0] - tmp[1][0])
parr[wi][5] += winner_append_point
# 진 사람 총내리고 이동
li = loser[2]
lx, ly, ld, ls, la, lc = parr[li]
# 총내리기
if la != 0:
gun_info[(lx, ly)].append(la)
gun_info[(lx, ly)].sort()
la = 0
# 진사람 이동하기
for i in range(4):
lnx, lny = lx + dx[(ld + i) % 4], ly + dy[(ld + i) % 4]
# 사람이 없고 빈칸이 아닐때까지 반복
if in_range(lnx, lny, n) and not is_in_person(lnx, lny, parr):
lx, ly = lnx, lny
ld = (ld + i) % 4
break
# 이동한 칸에 총이 있으면
if len(gun_info[(lx, ly)]):
# 총이 자신의 총보다 더 크면 총 먹음
if gun_info[(lx, ly)][-1] > la:
la = gun_info[(lx, ly)][-1]
gun_info[(lx, ly)].pop()
parr[li] = [lx, ly, ld, ls, la, lc]
wx, wy, wd, ws, wa, wc = parr[wi]
# 해당 칸에 떨어져 있는 총이 자신의 총보다 클경우
if len(gun_info[(wx, wy)]) > 0:
if gun_info[(wx, wy)][-1] > wa:
bwa = wa
wa = gun_info[(wx, wy)][-1]
gun_info[(wx, wy)].pop()
if bwa != 0:
gun_info[(wx, wy)].append(bwa)
gun_info[(wx, wy)].sort()
parr[wi] = [wx, wy, wd, ws, wa, wc]
ans = [p[5] for p in parr]
for a in ans:
print(a, end=" ")
main()
'알고리즘 > 코드트리' 카테고리의 다른 글
[코드트리] - 팩맨 (0) | 2023.09.27 |
---|---|
[코드트리] - 나무박멸 (1) | 2023.09.26 |
[코드트리] - 포탑부수기 (1) | 2023.09.25 |
[코드트리] - 시공의 돌풍 (0) | 2023.09.23 |
[코드트리] - 격자 숫자 놀이 (0) | 2023.09.22 |