백준 구현 대비 마법사상어와파이어볼

yjkim·2023년 7월 24일
0

알고리즘

목록 보기
33/60

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

direction=[[-1,0],[-1,1],[0,1],[1,1],[1,0],[1,-1],[0,-1],[-1,-1]]

def move():
  global graph
  tempgraph=[[[] for i in range(N)] for j in range(N)]
  for i in range(N):
    for j in range(N):
      if len(graph[i][j])>0:
        for t in graph[i][j]:
          m,s,d=t[0],t[1],t[2]
          ni,nj=(i+direction[d][0]*s)%N,(j+direction[d][1]*s)%N
          tempgraph[ni][nj].append([m,s,d])
  graph=tempgraph

def merge():
  for i in range(N):
    for j in range(N):
      if len(graph[i][j])>1:
        tm,ts=0,0
        for t in graph[i][j]:
          tm+=t[0]
          ts+=t[1]
        sm=tm//5
        if sm==0:
          graph[i][j]=[]
          continue
        ss=ts//len(graph[i][j])
        if oddoreven(graph[i][j]):
          graph[i][j]=[]
          for d in range(0,7,2):
            graph[i][j].append([sm,ss,d])
        else:
          graph[i][j]=[]
          for d in range(1,8,2):
            graph[i][j].append([sm,ss,d])
            

def oddoreven(g):
  for i in range(1,len(g)):
    if g[i][2]%2!=g[i-1][2]%2:
      return False
  
  return True


N,M,K=map(int ,input().split())

graph=[[[] for i in range(N)] for j in range(N)]
for i in range(M):
  r,c,m,s,d=map(int, input().split())  # map 함수의 반환값 이거 꼭 다시 공부
  graph[r-1][c-1].append([m,s,d])

while K>0:
  move()
  merge()
  K-=1
total=0


for i in range(N):
  for j in range(N):
    if len(graph[i][j])>0:
      for x in graph[i][j]:
        total+=x[0]


print(total)

# 인풋 순서 제발 잘 보고 풀자

구현까지는 수월하게 진행하였으나 input 과정에서 에러때문에 시간을 많이 잡아먹은 문제, (m,d,s 를 m,s,d로 대입하였음)

추가) 구글링하다가 깔끔한 코드가 있어서 도움될거같아 첨부함

N, M, K = map(int, input().split())
fireballs = []
for _ in range(M):
    _r, _c, _m, _s, _d = list(map(int, input().split()))
    fireballs.append([_r-1, _c-1, _m, _s, _d])

MAP = [[[] 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]

for _ in range(K):
    # 파이어볼 이동
    while fireballs:
        cr, cc, cm, cs, cd = fireballs.pop(0)
        nr = (cr + cs * dx[cd]) % N  # 1번-N번 행 연결되어있기 때문
        nc = (cc + cs * dy[cd]) % N
        MAP[nr][nc].append([cm, cs, cd])

    # 2개 이상인지 체크
    for r in range(N):
        for c in range(N):
            # 2개 이상인 경우 -> 4개의 파이어볼로 쪼개기
            if len(MAP[r][c]) > 1:
                sum_m, sum_s, cnt_odd, cnt_even, cnt = 0, 0, 0, 0, len(MAP[r][c])
                while MAP[r][c]:
                    _m, _s, _d = MAP[r][c].pop(0)
                    sum_m += _m
                    sum_s += _s
                    if _d % 2:
                        cnt_odd += 1
                    else:
                        cnt_even += 1
                if cnt_odd == cnt or cnt_even == cnt:  # 모두 홀수이거나 모두 짝수인 경우
                    nd = [0, 2, 4, 6]
                else:
                    nd = [1, 3, 5, 7]
                if sum_m//5:  # 질량 0이면 소멸
                    for d in nd:
                        fireballs.append([r, c, sum_m//5, sum_s//cnt, d])

            # 1개인 경우
            if len(MAP[r][c]) == 1:
                fireballs.append([r, c] + MAP[r][c].pop())

print(sum([f[2] for f in fireballs]))

출처:https://jennnn.tistory.com/77

profile
We may throw the dice, but the Lord determines how they fall

1개의 댓글

comment-user-thumbnail
2023년 7월 24일

이런 유용한 정보를 나눠주셔서 감사합니다.

답글 달기