AngelPlayer`s Diary

링크

https://www.acmicpc.net/problem/20056

 

 

 

 

문제 해석

격자 n * n
파이어볼 개수 m개
파이오볼은 위치 질량 방향 속력을 가짐
행열은 1,1부터 시작함
1번열과 n번열은 연결되어 있음


입력
- 첫 번째 줄 : nn, ll, kk
  nn : 격자 크기
  ll : 초기 파이어볼 개수
  kk : 이동 명령 횟수

- 나머지 줄 : rr cc mm ss dd
  rr : 행
  cc : 열
  mm : 질량
  ss : 속력
  dd : 방향

 

 

출력
남아있는 파이어볼 질량의 합

 

 

 

 

풀이 & 코드 해석

시뮬레이션이므로 문제에 주어진 조건을 그대로 구현하면 됩니다.

 

 

 

 

코드

dx = [-1, -1, 0, 1, 1, 1, 0, -1]
dy = [0, 1, 1, 1, 0, -1, -1, -1]


def print_arr(arrs):
    for i in range(len(arrs)):
        for j in range(len(arrs)):
            print(arrs[i][j], end=" ")
        print()


def move():
    global nn
    for i in range(len(li)):
        rr, cc, mm, ss, dd = li[i]

        nx = rr + dx[dd] * ss
        ny = cc + dy[dd] * ss

        if nx < 0:
            nx = (abs(nx) % nn) * -1
            nx = nx + nn

        if ny < 0:
            ny = (abs(ny) % nn) * -1
            ny = ny + nn

        if nx >= nn:
            nx = nx % nn

        if ny >= nn:
            ny = ny % nn


        if arr[nx][ny] == -1:
            arr[nx][ny] = i
            add_list[i].append(i)
            loc_list[i].extend([nx, ny])
        else:
            add_list[arr[nx][ny]].append(i)

    # print_arr(arr)
    # print(add_list)

def ball_merge():
    for i in range(len(add_list)):
        # 내 위치는 나만 있는 경우
        if len(add_list[i]) == 1:
            rr, cc, mm, ss, dd = li[i]
            new_rr = loc_list[i][0]
            new_cc = loc_list[i][1]

            next_li.append([new_rr, new_cc, mm, ss, dd])
        elif len(add_list[i]) == 0:
            continue
        # 합쳐지는 경우
        else:
            add_rr = loc_list[i][0]
            add_cc = loc_list[i][1]
            add_mm = 0
            add_ss = 0
            add_dd = li[add_list[i][0]][4]
            is_dd_same = True

            # 합치기
            for j in range(len(add_list[i])):
                now = add_list[i][j]

                now_rr, now_cc, now_mm, now_ss, now_dd = li[now]

                add_mm += now_mm
                add_ss += now_ss

                if is_dd_same == False:
                    continue

                if now_dd % 2 != add_dd % 2:
                    is_dd_same = False

            # 나누기
            add_mm = add_mm // 5
            add_ss = add_ss // len(add_list[i])

            # 0이라면 소멸
            if add_mm == 0:
                continue

            # 모든 방향이 동일하면
            if is_dd_same == True:
                for j in range(0, 7, 2):
                    next_li.append([add_rr, add_cc, add_mm, add_ss, j])
            else:
                for j in range(1, 8, 2):
                    next_li.append([add_rr, add_cc, add_mm, add_ss, j])


nn, ll, kk = list(map(int, input().split()))

li = []

for i in range(ll):
    rr, cc, mm, ss, dd = (list(map(int, input().split())))
    li.append([rr - 1, cc - 1, mm, ss, dd])

# 이동 명령 횟수만큼 반복
for z in range(kk):
    add_list = [[] for i in range(len(li))] # 리스트의 i번째 위치 볼과 합쳐질 볼
    loc_list = [[] for i in range(len(li))]
    arr = [[-1] * nn for i in range(nn)] # 이동한 위치 찍기
    next_li = []

    # 이동
    move()

    # 합치기
    ball_merge()

    li = next_li

ans = 0
for i in range(len(li)):
    ans += li[i][2]
print(ans)

 

 

 

 

발생한 문제 & 해결 방안

이 문제에서 가장 헷갈렸던 부분은 파이어볼을 나눌 때 위치는 그대로이고 방향이 서로 다른 4개의 파이어볼을 만들어야 한다는 점이었습니다. 

 

문제를 명확하게 이해하고 푸는게 중요합니다.

 

 

 

 

 

 

해당 코드는 에디터가 코드 연습을 위해 직접 작성하였습니다.

혹시 오류가 있거나 더 좋은 코드 방향성을 아시는 분은 댓글로 남겨주시면 감사하겠습니다!

python source : https://github.com/ssh5212/conding-test-practice

java source : https://github.com/ssh5212/coding-test-java

공유하기

facebook twitter kakaoTalk kakaostory naver band