최근 구현 문제를 푸는데 있어서 부족함이 있음을 깨닫고, 복잡하고 긴 글을 가진 문제를 정확하게 해석하는 문제들을 해결하려고 노력 중이다.
바로 이 주사위 굴리기 2 같은 문제이다.
https://www.acmicpc.net/problem/23288
문제가 정말 친절하면서도, 복잡하다.
천천히 독해해보도록 하자.
먼저 보드게임판이 있다고 상상을 해보자. 맨 위쪽 끝에 주사위가 위치해있다.
1가 맨 위에 그려져있고, 6이 바닥에 있다.
처음에는, 오른쪽으로 구른다. 그러면, 오른쪽에 그려져있는 3이 밑으로 위치한다.
그 이후, 아랫면에 있는 3이랑, 보드게임판 1이랑 크기의 차이를 비교하여, 이동 방향 변화를 맞춘다.
이후, 보드게임판의 1이 어떻게 이어져있는지 파악한다. 이어진 같은 수의 개수 만큼, 수를 곱해서 총 점수에 더해준다.
n,m,k=map(int,input().split())
data=list(list(map(int,input().split())) for _ in range(n))
from collections import deque
dice=[0,2,4,1,3,5,6]
d=0
x,y=0,0
answer=0
def roll(d):
if d==0: #east
dice[4],dice[3],dice[2],dice[6]=dice[3],dice[2],dice[6],dice[4]
elif d==1: #south
dice[1],dice[3],dice[5],dice[6]=dice[6],dice[1],dice[3],dice[5]
elif d==2: #west
dice[4],dice[3],dice[2], dice[6]=dice[6],dice[4],dice[3],dice[2]
else: #north
dice[1],dice[3],dice[5],dice[6] = dice[3],dice[5],dice[6],dice[1]
def play():
global d,answer,x,y
nx,ny=x,y
if d==0:
nx,ny=x,y+1
if 0<=nx<n and 0<=ny<m:
roll(d)
answer+=data[nx][ny]*score(nx,ny)
else:
d=2
play()
return
elif d==1:
nx,ny=x+1,y
if 0<=nx<n and 0<=ny<m:
roll(d)
answer+=data[nx][ny]*score(nx,ny)
else:
d=3
play()
return
elif d==2:
nx,ny=x,y-1
if 0<=nx<n and 0<=ny<m:
roll(d)
answer+=data[nx][ny]*score(nx,ny)
else:
d=0
play()
return
else:
nx,ny=x-1,y
if 0<=nx<n and 0<=ny<m:
roll(d)
answer+=data[nx][ny]*score(nx,ny)
else:
d=1
play()
return
if dice[6]>data[nx][ny]:
d+=1
if d==4:
d=0
elif dice[6]<data[nx][ny]:
d-=1
if d==-1:
d=3
x,y=nx,ny
return
dx=[0,0,-1,1]
dy=[-1,1,0,0]
def score(xx,yy):
count=1
visited=list(list(0 for _ in range(m)) for _ in range(n))
q=deque()
q.append([xx,yy])
visited[xx][yy]=1
while q:
x,y=q.popleft()
for i in range(4):
nx=x+dx[i]
ny=y+dy[i]
if 0<=nx<n and 0<=ny<m and not visited[nx][ny] and data[nx][ny]==data[xx][yy]:
q.append([nx,ny])
count+=1
visited[nx][ny]=1
return count
for _ in range(k):
play()
print(answer)
이런 복잡한 문제가 나올 때일수록, 각 역할을 하는 함수로 분할하는 습관을 들여야 할 것이다.
먼저 초기 주사위에 대한 변수 dice가 있다. dice의 index는 주사위의 위치를 임의로 적은 것이고, 숫자는 눈을 의미한다.
roll 함수는 동, 남 , 서, 북 방향으로 주사위가 굴렀을 때 일어나는 주사위의 변화를 저장한다.
play는 실제로 주사위를 해당 방향으로 굴리는 함수이다.
이 때 두가지 경우가 존재한다.
첫 째로는, 실제로 진행하고자 하는 방향으로 주사위가 구를 수 있는 경우이다. 진짜로 굴려서, 점수를 찾는다.
두번째는, 진행하고자 하는 방향이 판 밖으로 나가야하는 경우이다. 이럴 때는, 가려고 한 곳의 반대편으로 돌아야한다.
방향으로 반대로 바꾸고, 다시 play 함수를 재귀적으로 실행하자. 판은 최소 2 by 2이기 때문에, 방향을 바꿨을 때 또 벽에 막히는 경우는 존재하지 않는다.
이후 score 함수를 통해서 점수를 계산한다. 이 때, bfs를 사용해서 해당 발판과 이어져있는 숫자들의 수가 몇개인지 파악할 수 있다.
play 함수의 마지막 부분에서는, 해당 점수 매기기가 끝나고 다음 주사위의 이동 방향을 결정해준다.
현재 주사위 밑에 있는 값과 보드에서의 값을 비교하여, 방향을 정해주자.
해당 play를 k번 진행하면, 총 얻을 수 있는 점수를 파악할 수 있다.
P.S. 나는 <= 에서 =을 빼먹어서 무한 루프가 나는 걸 파악하기 위해 1시간을 소비했다...
'Computer Science > Algorithm' 카테고리의 다른 글
[Python 3] BOJ 1256 사전 (1) | 2024.03.08 |
---|---|
[Python 3] LEETCODE 141. Linked List Cycle (0) | 2024.03.06 |
[Python 3] BOJ 2036 수열의 점수 (0) | 2024.03.04 |
[Python 3] BOJ 1253 좋다 (1) | 2024.03.02 |
[Python 3] BOJ 26093 고양이 목에 리본 달기 (0) | 2024.02.24 |