코딩테스트/삼성 기출

삼성기출, 백준 23288 주사위 굴리기2 파이썬 코드/풀이

RyanKwon 2022. 10. 9. 15:57
728x90

한시간 정도 잡고 풀었는데 한시간 반 걸렸다.

예제에 안되는 문제가 있어서 디버깅 해보니까 주사위 돌리는 과정에서 딥카피가 안돼서 오류가 나고 있었다.

해당 부분 for문으로 값을 넣어줘서 딥카피로 해결했다.

 

총 4개 함수를 만들어서 풀었다.

 

1. 이동 방향 결정 + 주사위 모양 바꾸기 

2. 주사위가 이동하는 부분의 좌표 확인

3. 좌표 확인시 뒤로 되돌아가는 경우 이동방향 재결정 및 주사위모양 다시바꾸기

4. 점수계산

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

grid = []

for i in range(N):
  grid.append(list(map(int, input().split())))

dice = [[0 for i in range(3)] for j in range(4)]

dice[0][1] = 2
dice[1][0] = 4
dice[1][1] = 1
dice[1][2] = 3
dice[2][1] = 5
dice[3][1] = 6

#1회차에는 오른쪽으로 굴러감.
#점수 계산
#주사위 갈 방향 결정 -> 주사위 모습 변경 및 이동하느 좌표 리턴

RIGHT, LEFT, DOWN, UP = 0, 2, 1, 3


def roll_dice(dice, prev_dir, loc, cnt):  #굴릴 방향 결정 및 주사위 모습 변경
  y, x = loc[0], loc[1]
  A = dice[3][1]
  B = grid[y][x]

  if A > B:
    dir = (prev_dir + 1) % 4
  elif B > A:
    dir = (prev_dir + 3) % 4
  else:
    dir = prev_dir

  tmp_dice = [[0 for i in range(3)] for j in range(4)]

  for i in range(4):
    for j in range(3):
      tmp_dice[i][j] = dice[i][j]

  if cnt == 0:
    dir = RIGHT

  if dir == RIGHT:  #동
    dice[1][0] = tmp_dice[3][1]
    dice[1][1] = tmp_dice[1][0]
    dice[1][2] = tmp_dice[1][1]
    dice[3][1] = tmp_dice[1][2]
  elif dir == LEFT:  #서
    dice[1][0] = tmp_dice[1][1]
    dice[1][1] = tmp_dice[1][2]
    dice[1][2] = tmp_dice[3][1]
    dice[3][1] = tmp_dice[1][0]
  elif dir == DOWN:  #남
    for i in range(4):
      dice[i][1] = tmp_dice[(i + 3) % 4][1]
  else:  #북
    for i in range(4):
      dice[i][1] = tmp_dice[(i + 1) % 4][1]

  return dice, dir


def re_roll_dice(dice, prev_dir, loc):  #주사위 방향 반대 설정 및 주사위 모습 변경
  dir = (prev_dir + 2) % 4

  tmp_dice = [[0 for i in range(3)] for j in range(4)]

  for _ in range(2):
    for i in range(4):
      for j in range(3):
        tmp_dice[i][j] = dice[i][j]

    if dir == RIGHT:  #동
      dice[1][0] = tmp_dice[3][1]
      dice[1][1] = tmp_dice[1][0]
      dice[1][2] = tmp_dice[1][1]
      dice[3][1] = tmp_dice[1][2]
    elif dir == LEFT:  #서
      dice[1][0] = tmp_dice[1][1]
      dice[1][1] = tmp_dice[1][2]
      dice[1][2] = tmp_dice[3][1]
      dice[3][1] = tmp_dice[1][0]
    elif dir == DOWN:  #남
      for i in range(4):
        dice[i][1] = tmp_dice[(i + 3) % 4][1]
    else:  #북
      for i in range(4):
        dice[i][1] = tmp_dice[(i + 1) % 4][1]

  return dice, dir


def new_loc(dice, loc, dir):  #이동좌표리턴
  y, x = loc
  ny, nx = y, x
  if dir == RIGHT:  #동
    nx = x + 1
    if nx >= M:
      nx = x - 1
      dice, dir = re_roll_dice(dice, dir, loc)
  elif dir == LEFT:  #서
    nx = x - 1
    if nx < 0:
      nx = x + 1
      dice, dir = re_roll_dice(dice, dir, loc)
  elif dir == DOWN:  #남
    ny = y + 1
    if ny >= N:
      ny = y - 1
      dice, dir = re_roll_dice(dice, dir, loc)
  else:  #북
    ny = y - 1
    if ny < 0:
      ny = y + 1
      dice, dir = re_roll_dice(dice, dir, loc)

  return dice, dir, [ny, nx]


def calculation(loc):
  y, x = loc
  B = grid[y][x]
  stack = [loc]
  visited = [[0 for i in range(M)] for j in range(N)]
  cnt = 0
  # print(loc)
  while stack:
    y, x = stack[-1]

    stack = stack[:-1]
    if visited[y][x] == 1:
      continue
    visited[y][x] = 1
    cnt += 1
    for dy, dx in [[1, 0], [-1, 0], [0, 1], [0, -1]]:
      ny, nx = y + dy, x + dx
      if ny >= N or ny < 0 or nx >= M or nx < 0:
        continue
      if grid[ny][nx] == B and visited[ny][nx] == 0:
        stack.append([ny, nx])

  return cnt * B


dir = RIGHT
loc = [0, 0]
answer = 0
for cnt in range(total):
  dice, dir = roll_dice(dice, dir, loc, cnt)
  dice, dir, loc = new_loc(dice, loc, dir)
  answer += calculation(loc)

print(answer)
728x90