import sys
input = sys.stdin.readline
def move(target):
x,y,dire = chess[target]
nx = x + dx[dire]
ny = y + dy[dire]
if not(0<=nx<N) or not(0<=ny<N) or arr[nx][ny] == 2:
dire = reverse_dire[dire]
chess[target] = [x,y,dire]
nx = x + dx[dire]
ny = y + dy[dire]
if not(0<=nx<N) or not(0<=ny<N) or arr[nx][ny] == 2:
return 0
slice_idx = 0
for ind,horse in enumerate(chess_map[x][y]):
if horse == target:
slice_idx = ind
break
move_items = chess_map[x][y][slice_idx:]
chess_map[x][y] = chess_map[x][y][:slice_idx]
if arr[nx][ny]:
move_items.reverse()
chess_map[nx][ny].extend(move_items)
for ind in move_items:
chess[ind] = [nx,ny,chess[ind][2]]
return len(chess_map[nx][ny])
N,M = map(int,input().split())
arr = [list(map(int,input().split())) for _ in range(N)]
chess = [[] for _ in range(M)]
chess_map = [[[] for _ in range(N)] for _ in range(N)]
chess_input = [list(map(lambda x : x-1,map(int,input().split()))) for _ in range(M)]
dx = [0,0,-1,1]
dy = [1,-1,0,0]
reverse_dire = [1,0,3,2]
for ind,info in enumerate(chess_input):
x,y,dire = info
chess[ind] = [x,y,dire]
chess_map[x][y].append(ind)
cnt = 0
break_flag = False
while cnt <= 1000:
cnt += 1
for k in range(M):
stack_size = move(k)
if stack_size >= 4:
break_flag = True
break
if break_flag:
break
print(-1 if cnt > 1000 else cnt)
N = int(input())
arr = [list(map(int,input().split())) for _ in range(N)]
result = float('inf')
for x in range(N):
for y in range(N):
for d1 in range(1,y+1):
for d2 in range(1,N-y+1):
if 0<=x+d1+d2<N and 0<=y+d2-d1<N and 0<=y+d2<N and 0<=y-d1<N:
max_person = 0
min_person = float('inf')
visited = [[True]*N for _ in range(N)]
temp = 0
d1_move = 0
d1_flag = True
d2_move = 0
d2_flag = True
for x_five in range(x,x+d2+d1+1):
for y_five in range(y-d1_move,y+d2_move+1):
visited[x_five][y_five] = False
temp += arr[x_five][y_five]
if d1_flag:
if d1_move == d1:
d1_flag = False
d1_move -=1
else:
d1_move += 1
else:
d1_move -= 1
if d2_flag:
if d2_move == d2:
d2_flag = False
d2_move -= 1
else:
d2_move += 1
else:
d2_move -= 1
max_person = max(max_person,temp)
min_person = min(min_person,temp)
for x_area,y_area in [[(0,x+d1),(0,y+1)],[(0,x+d2+1),(y+1,N)],[(x+d1,N),(0,y-d1+d2)],[(x+d2+1,N),(y-d1+d2,N)]]:
temp = 0
for i in range(x_area[0],x_area[1]):
for j in range(y_area[0],y_area[1]):
if visited[i][j]:
temp += arr[i][j]
max_person = max(max_person,temp)
min_person = min(min_person,temp)
result = min(result,max_person - min_person)
print(result)
def get_points(N):
temp = []
for x in range(1,N-1):
for y in range(2,N):
for d1 in range(1,y):
for d2 in range(1,N-y+1):
if x + d1 + d2 >N:
break
temp.append([x,y,d1,d2])
return temp
def divide_city(x,y,d1,d2):
board = [[0]*N for _ in range(N)]
for i in range(x+d1):
for j in range(y):
board[i][j] = 1
for i in range(x+d2):
for j in range(y,N):
board[i][j] = 2
for i in range(x+d1-1,N):
for j in range(y-d1+d2-1):
board[i][j] = 3
for i in range(x+d2,N):
for j in range(y-d1+d2-1,N):
board[i][j] = 4
for i in range(d1+d2+1):
for j in range(-(d1-abs(i-d1)), d2+1-abs(i-d2)):
board[x+i-1][y+j-1] = 5
return board
N = int(input())
arr = [list(map(int,input().split())) for _ in range(N)]
divide_possible_list = get_points(N)
result = float('inf')
for x,y,d1,d2 in divide_possible_list:
board = divide_city(x,y,d1,d2)
persons = [0]*5
for i in range(N):
for j in range(N):
persons[board[i][j]-1] += arr[i][j]
diff = max(persons) - min(persons)
if diff < result:
result = diff
print(result)
from collections import Counter
def move_robot(mad_ro,ro):
new_robot = []
for mad_x,mad_y in mad_ro:
ro_distance = float('inf')
ro_direction = -1
for i in range(9):
mad_nx = mad_x + dx[i]
mad_ny = mad_y + dy[i]
if 0<= mad_nx < R and 0<= mad_ny <C:
distance = abs(mad_nx - ro[0]) + abs(mad_ny-ro[1])
if ro_distance > distance:
ro_distance = distance
ro_direction = i
new_x = mad_x + dx[ro_direction]
new_y = mad_y + dy[ro_direction]
new_robot.append((new_x,new_y))
return new_robot
def bomb_robot(mad_ro):
count_mad_ro = Counter(mad_ro)
new_mad_ro = set()
for key,value in count_mad_ro.items():
if value == 1:
new_mad_ro.add(key)
return new_mad_ro
R,C = map(int,input().split())
arr = [list(input()) for _ in range(R)]
mad_robots = set()
robot = (0,0)
for i in range(R):
for j in range(C):
if arr[i][j] == 'R':
mad_robots.add((i,j))
arr[i][j] = '.'
elif arr[i][j] == 'I':
robot = (i,j)
arr[i][j] = '.'
command = list(map(lambda x : x-1, map(int,list(input()))))
dx = [1,1,1,0,0,0,-1,-1,-1]
dy = [-1,0,1,-1,0,1,-1,0,1]
flag = False
answer = 0
for time in range(len(command)):
x,y = robot
nx = x + dx[command[time]]
ny = y + dy[command[time]]
if (nx,ny) in mad_robots:
flag = True
answer = time + 1
break
robot = (nx,ny)
mad_robots = move_robot(mad_robots,robot)
if robot in mad_robots:
flag = True
answer = time + 1
break
mad_robots = bomb_robot(mad_robots)
if flag:
print(f'kraj {answer}')
else:
arr[robot[0]][robot[1]] = 'I'
for mad in mad_robots:
arr[mad[0]][mad[1]] = 'R'
for row in arr:
print(''.join(row))
from collections import deque
import sys
input = sys.stdin.readline
N,M,K = map(int,input().split())
AppendList = [list(map(int,input().split())) for _ in range(N)]
tree_info = [[[] for _ in range(N)] for _ in range(N)]
result = 0
forest = [[5]*N for _ in range(N)]
for _ in range(M):
X,Y,age = map(int,input().split())
tree_info[X-1][Y-1].append(age)
result += 1
dx = [-1,-1,-1,0,0,1,1,1]
dy = [-1,0,1,-1,1,-1,0,1]
for year in range(K):
for x in range(N):
for y in range(N):
if len(tree_info[x][y])>0:
temp = []
summer_forest = 0
cnt = 0
limited = len(tree_info[x][y])
while cnt < limited:
age = tree_info[x][y].pop()
if forest[x][y] >= age:
forest[x][y] -= age
temp.append(age+1)
else:
summer_forest += (age//2)
result -= 1
cnt += 1
temp.sort(reverse=True)
tree_info[x][y].extend(temp)
forest[x][y] += summer_forest
forest[x][y] += AppendList[x][y]
for x in range(N):
for y in range(N):
spread_cnt = 0
if tree_info[x][y]:
for val in tree_info[x][y]:
if val%5 == 0:
spread_cnt += 1
if spread_cnt:
for i in range(8):
nx = x + dx[i]
ny = y + dy[i]
if 0<=nx<N and 0<=ny<N:
result += spread_cnt
tree_info[nx][ny].extend([1]*spread_cnt)
print(result)
구현을 하는 문제인데, 문제에 주어진 조건대로 면 된다. 문제는 시간초과의 벽이 너무 컸다. 시간초과가 나지 않도록 최대한 문제에 주어진 조건을 한번에 구현할수 있도록 하는게 중요했다.
import sys
input = sys.stdin.readline
N,M,K = map(int,input().split())
store = [list(map(int,input().split())) for _ in range(N)]
tree_info = [[{} for _ in range(N)] for _ in range(N)]
forest = [[5]*N for _ in range(N)]
tree_cnt = 0
for _ in range(M):
x,y,age = map(int,input().split())
tree_info[x-1][y-1][age] = 1
tree_cnt += 1
dx = [-1,-1,-1,0,0,1,1,1]
dy = [-1,0,1,-1,1,-1,0,1]
for _ in range(K):
for x in range(N):
for y in range(N):
if tree_info[x][y]:
summer_forest = 0
new_dict = {}
for age in sorted(tree_info[x][y].keys()):
if forest[x][y] >= age * tree_info[x][y][age]:
forest[x][y] -= age * tree_info[x][y][age]
new_dict[age+1] = tree_info[x][y][age]
else:
if forest[x][y] // age:
new_dict[age+1] = forest[x][y]//age
forest[x][y] -= age*new_dict[age+1]
if tree_info[x][y][age] - new_dict[age+1]:
summer_forest += (age//2) * (tree_info[x][y][age] - new_dict[age+1])
tree_cnt -= (tree_info[x][y][age] - new_dict[age+1])
else:
summer_forest += (age//2)*tree_info[x][y][age]
tree_cnt -= tree_info[x][y][age]
tree_info[x][y] = new_dict
forest[x][y] += summer_forest
forest[x][y] += store[x][y]
for x in range(N):
for y in range(N):
spread_cnt = 0
for age in tree_info[x][y]:
if not age%5:
spread_cnt += tree_info[x][y][age]
if spread_cnt:
for i in range(8):
nx = x + dx[i]
ny = y + dy[i]
if 0 <= nx <N and 0<=ny<N:
if tree_info[nx][ny].get(1):
tree_info[nx][ny][1] += spread_cnt
else:
tree_info[nx][ny][1] = spread_cnt
tree_cnt += spread_cnt
print(tree_cnt)
import sys
input = sys.stdin.readline
def roll(A,B):
if A[0] >= B[0] and A[1] < B[1]:
dx = A[0]-B[0]
dy = B[1]-A[1]
return (B[0]+dy,B[1]+dx)
elif A[0] >= B[0] and A[1] >= B[1]:
dx = A[0] - B[0]
dy = A[1] - B[1]
return (B[0]-dy,B[1]+dx)
elif A[0] < B[0] and A[1] < B[1]:
dx = B[0]-A[0]
dy = B[1]-A[1]
return (B[0]+dy,B[1]-dx)
else:
dx = B[0]-A[0]
dy = A[1]-B[1]
return (B[0]-dy,B[1]-dx)
def dragon(cur_gener,total_gener):
global dragon_list
if cur_gener == total_gener:
return
tail_position = dragon_list[-1]
dragon_length = len(dragon_list)
for ind in range(dragon_length-2,-1,-1):
dragon_list.append(roll(dragon_list[ind],tail_position))
dragon(cur_gener+1,total_gener)
N = int(input())
# x,y 시작점 d는 시작 방향 g는 세대
dx = [1,0,-1,0]
dy = [0,-1,0,1]
arr = [[0]*101 for i in range(101)]
for _ in range(N):
x,y,dire,gener = map(int,input().split())
dragon_list = [(x,y),(x+dx[dire],y+dy[dire])]
if gener:
dragon(0,gener)
for position in dragon_list:
arr[position[1]][position[0]] = 1
result = 0
for y in range(100):
for x in range(100):
if arr[x][y] + arr[x+1][y] + arr[x+1][y+1] + arr[x][y+1] == 4:
result += 1
print(result)
이 드래곤 커브는 끝에 있는 점을 기준으로 현재까지 온 경로들을 전부 시계 방향으로 90도 회전을 해주는 것을 계속 반복한다.
처음 풀었던 방식은 어렵게 생각해서 푼 문제이다.
드래곤 커브의 각 점들의 위치를 한 리스트에 넣어준다. 그러면 끝점을 찾아주고, 그 끝점을 기준으로 끝점을 제외한 나머지 점들의 위치를 파악해서, 옮겨주는 작업을 해주었다.
좌표계로 그려보면 알겠지만, 끝점을 원점으로 생각해서, 그 점을 기준으로 1,2,3,4 사분면에 있을때 회전하는 위치를 계산해주었다.
1사분면에 있으면 1사분면의 y축 값은 x축값이 되고, x축의 값은 +y축값이 된다.
2사분면에 있으면 2사분면의 x축값은 +y축값이 되고, y축값은 -x축 값이 된다.
이런식으로 구분을 해서, 각 끝점을 기준으로 움직인 위치를 찾아서 드래곤 커브 리스트에 넣어준다.
여기서 주의 해야할 점은 두가지인데, 문제에 주어진 xy좌표축은 수직방향으로 위로 올라갈수록 y축 값이 줄어드는 것이다.
그리고 두번째는 끝점을 기준으로 뒤에서부터 판별을해야 한다는 것이다.
이렇게 모든 세대를 돌리고 난뒤에 101*101 행렬에 점을 찍어주면 된다. 그리고 마지막으로 네 귀퉁이에 전부 1인 경우에를 세어서 결과로 출력하면 된다.
import sys
input = sys.stdin.readline
N = int(input())
arr = [[0]*101 for _ in range(101)]
dx = [1,0,-1,0]
dy = [0,-1,0,1]
for _ in range(N):
x,y,dire,gener = map(int,input().split())
# dire 0 ->1
# 1->2
# 2->3
# 3->0
move_list = [dire]
arr[y][x] = 1
for _ in range(gener):
temp = []
for i in range(len(move_list)-1,-1,-1):
temp.append((move_list[i]+1)%4)
move_list.extend(temp)
for i in move_list:
nx = x + dx[i]
ny = y + dy[i]
arr[ny][nx] = 1
x,y = nx,ny
result = 0
for y in range(100):
for x in range(100):
if arr[y][x] + arr[y+1][x] + arr[y][x+1] + arr[y+1][x+1] == 4:
result += 1
print(result)
좀 더 쉬운 풀이는 다음과 같다.
진행방향만 넣어주는 것이다.
90도 시계방향을 회전하면 다음 진행반향은 현재 진행방향의 +1 의 modulo 4 연산을 해주면 된다.
# # 3190 뱀
from collections import deque
N = int(input())
K = int(input())
apples = set(tuple(map(int,input().split())) for _ in range(K))
command_cnt = int(input())
# direction 0동 1남 2서 3북
dx = [0,1,0,-1]
dy = [1,0,-1,0]
commands = []
snakes = deque()
snakes.append((1,1))
for _ in range(command_cnt):
time,dire = input().split()
if dire == 'D':
dire = 1
else:
dire = -1
commands.append((int(time),dire))
snake_times = 0
ind = 0
snake_direction = 0
flag = True
next_time = commands[0][0]
break_flag = False
while True:
if flag:
next_time = commands[ind][0]
snake_times += 1
snake_head = snakes[0]
next_x = snake_head[0] + dx[snake_direction]
next_y = snake_head[1] + dy[snake_direction]
if 1<= next_x <=N and 1<= next_y<=N:
if (next_x,next_y) not in snakes:
if (next_x,next_y) in apples:
snakes.appendleft((next_x,next_y))
apples.remove((next_x,next_y))
else:
snakes.pop()
snakes.appendleft((next_x,next_y))
else:
break_flag = True
else:
break_flag = True
if break_flag:
break
if snake_times == next_time:
snake_direction = (snake_direction + commands[ind][1])%4
ind += 1
if ind == command_cnt:
flag = False
print(snake_times)
이 문제는 큐와 스택같은 자료구조에 대해서 알면 쉽게 풀 수 있는 문제이다.
물론 나는 오래걸렸다.
먼저 여기서는 방향 전환이 왼쪽, 오른쪽 밖에 없다. 만약에 동남서북(0,1,2,3) 형태로 방향을 저장해놓은 상태라면, 왼쪽일때는 -1을 해주고 오른쪽일때는 +1 을 해주고, 4로 나눈 나머지를 구해주면 된다.
기본적인 방법은 다음과 같다. snake는 기본적으로 deque 형태로 저장을 해준다.
먼저 snake_head를 기준으로 탐색해야한다. 나는 deque에서 왼쪽 즉 처음 들어온부분이 head로 가정했기 때문에, snake[0]을 가져온다. 그리고 snake의 방향에 맞게 진행을 해준다. 만약 범위를 벗어나거나 이미 snake에 있는 위치로 갈시, 예외처리를 해주고, 즉각적으로 멈출수 있게 break_flag를 해주었다.
그리고 둘 중 하나인데 만약에 뱀의 머리가 움직인 위치에 사과가 있을때에는, 뱀의 길이가 늘어난 것이기 때문에 새로운 head의 위치를 snake에 추가해주고, apple를 없애준다.
만약에 사과가 없을때에는 꼬리부분을 없애주고, 새로운 머리부분을 추가해준다.
매 타임마다 위와 같이 진행을 해주면 되는데, 여기서 명령어가 주어진다. 여기서 주의할 점은 시간이 끝난뒤 시행되는 것이기 때문에 time을 늘려주는 로직을 이 명령어를 조작하는 부분보다 상위에 두어야한다.
뱀이 움직이 시간이 끝난 시간과 명령어에 들어온 시간이 같으면 명령어 대로 방향을 바꿔준다.
그리고 이 명령어의 길이가 3일때, 만약에 3번째 명령까지 반영해서 방향을 바꿔주었으면 마지막 방향대로 계속 진행을 해야하기 때문에 flag를 통해 예외 처리를 해주었다.
# # 3190 뱀
from collections import deque
N = int(input())
K = int(input())
board = [[0]*(N+1) for _ in range(N+1)]
for _ in range(K):
x,y = map(int,input().split())
board[x][y] = 1
command_cnt = int(input())
# direction 0동 1남 2서 3북
dx = [0,1,0,-1]
dy = [1,0,-1,0]
commands = []
snakes = deque()
snakes.append((1,1))
board[1][1] = 2
for _ in range(command_cnt):
time,dire = input().split()
if dire == 'D':
dire = 1
else:
dire = -1
commands.append((int(time),dire))
snake_times = 0
ind = 0
snake_direction = 0
next_time,next_direction = commands[0]
break_flag = True
while True:
snake_times += 1
snake_head = snakes[0]
next_x = snake_head[0] + dx[snake_direction]
next_y = snake_head[1] + dy[snake_direction]
if 1<= next_x <=N and 1<= next_y<=N:
if board[next_x][next_y] != 2:
if board[next_x][next_y] == 1:
snakes.appendleft((next_x,next_y))
board[next_x][next_y] = 2
else:
board[next_x][next_y] = 2
tail_x,tail_y = snakes.pop()
board[tail_x][tail_y] = 0
snakes.appendleft((next_x,next_y))
break_flag = False
if break_flag:
break
break_flag = True
if snake_times == next_time:
snake_direction = (snake_direction + next_direction)%4
if ind < command_cnt-1:
ind += 1
next_time,next_direction = commands[ind]
print(snake_times)
위의 내가 했던 부분과 거의 동일하다. 대신 board라는 2차원 리스트에 뱀의 위치와 사과의 위치를 표시해주었다 이렇게 하면, 첫번째 코드에서 썼던 not in snakes와 같은 logN이 걸리는 시간이 좀 더 줄어드는 장점이 있다.
# 14503 로봇 청소기
# r,c 는 r은 북쪽(X) c는 서쪽(Y)
# 동서남북
# sudo
# 1. 현재위치 청소
# 2. 현재 위치에서 왼쪽으로 회전 + 전진 -> 청소 반복
# 없으면 그 방향으로 계속 회전
# 4방향 전부 청소 완료하면 한칸 후진
# 후진이 안되면 멈춤
# d 0,1,2,3 북동남서
# 빈칸은 0, 벽은 1
N,M = map(int,input().split())
robotX,robotY,direction = map(int,input().split())
arr = [list(map(int,input().split())) for _ in range(N)]
rotate = [3,0,1,2]
visited = [[True] *M for _ in range(N)]
cnt = 1
stack = [(robotX,robotY,direction)]
dx = [-1,0,1,0]
dy = [0,1,0,-1]
visited[robotX][robotY] = False
while stack:
x,y,cu_dire = stack.pop()
if visited[x][y]:
visited[x][y] = False
cnt += 1
for _ in range(4):
nx = x + dx[rotate[cu_dire]]
ny = y + dy[rotate[cu_dire]]
if 0<= nx <N and 0<= ny<M:
if visited[nx][ny] and not arr[nx][ny]:
stack.append((nx,ny,rotate[cu_dire]))
break
cu_dire = rotate[cu_dire]
else:
reverse_dire = (cu_dire+2)%4
nx = x + dx[reverse_dire]
ny = y + dy[reverse_dire]
if 0<= nx< N and 0<= ny <M and not arr[nx][ny]:
stack.append((nx,ny,cu_dire))
else:
break
print(cnt)
이 문제는 문제에 주어진 조건대로 구현을 하는 문제였다.
문제에 주어진 조건대로 구현을 하면 되는데, 여기서 몇가지 주의점이 있다. 보통 DFS나 BFS에서는 시간을 아껴주기 위해, stack에 append 할때 방문을 표시해준다. 하지만 여기서는 한번 청소했던 곳을 다시 방문할 수 있고, 청소는 단 한번만 해주기 때문에, stack에서 빼줄때, 그때 visitied를 방문표시를 해주고, 청소회수를 늘려주었다. 이러는게 문제에 주어진 구현 순서인 1번에 적합한 것 같다.
현재 위치를 청소한다.
현재 위치에서 현재 방향을 기준으로 왼쪽방향부터 차례대로 탐색을 진행한다.
왼쪽 방향에 아직 청소하지 않은 공간이 존재한다면, 그 방향으로 회전한 다음 한 칸을 전진하고 1번부터 진행한다.
왼쪽 방향에 청소할 공간이 없다면, 그 방향으로 회전하고 2번으로 돌아간다.
네 방향 모두 청소가 이미 되어있거나 벽인 경우에는, 바라보는 방향을 유지한 채로 한 칸 후진을 하고 2번으로 돌아간다.
네 방향 모두 청소가 이미 되어있거나 벽이면서, 뒤쪽 방향이 벽이라 후진도 할 수 없는 경우에는 작동을 멈춘다.
2.1 ~ 2.2 구간이 중간에 있는 반복문에 있는 부분이다. 여기서는 사전에 작업을 해주었다. 위에 주석에도 있지만, 0,1,2,3을 북동남서로 저장해주고, 그에 해당되는 dx,dy를 구현해주었다.
그리고, rotate라는 변수에, 인덱스값은 현재의 방향 그리고 값은 왼쪽으로 회전시 나오는 방향을 넣어주었다.
평소에는 북남동서등 같은 방향끼리, 하는 경우가 많은데 여기서는 북동남서로 2칸씩 떨어트린 이유는 후진을 구현할때, 이렇게 2칸씩 떨어트려주면 (direction+2)%4 로 하면 쉽게 방향을 구할 수 있기 때문이다. 정 아니면 rotate와 동일하게 후진시 변경되는 리스트를 미리 만들어둬도 된다.
이렇게 반복문을 다 돌렸는데도 한번도 만족하지 않으면, else로 들어가 2.3~2.4 로직을 진행한다.
# 14499 주사위 굴리기
# N*M 지도
# 주사위는 윗면이 1 동쪽방향이 3인 상태로 놓아진다.
def roll(direction,nx,ny):
global dice,map_list
if direction == 1:
dice[0],dice[2],dice[3],dice[5] = dice[3],dice[0],dice[5],dice[2]
elif direction == 2:
dice[0],dice[2],dice[3],dice[5] = dice[2],dice[5],dice[0],dice[3]
elif direction == 3:
dice[0],dice[1],dice[4],dice[5] = dice[4],dice[0],dice[5],dice[1]
else:
dice[0],dice[1],dice[4],dice[5] = dice[1],dice[5],dice[0],dice[4]
if map_list[nx][ny]:
dice[5] = map_list[nx][ny]
map_list[nx][ny] = 0
else:
map_list[nx][ny] = dice[5]
N,M,X,Y,K = map(int,input().split())
map_list = [list(map(int,input().split())) for _ in range(N)]
# [1,2,3,4,5,6]
# 동쪽 1 [4,2,1,6,5,3]
# 서쪽 2 [3,2,6,1,5,4]
# 북쪽 3 [5,1,3,4,6,2]
# 남쪽 4 [2,6,3,4,1,5]
dice = [0]*6
dire = [(0,1),(0,-1),(-1,0),(1,0)]
command_list = list(map(int,input().split()))
for command in command_list:
nx = X + dire[command-1][0]
ny = Y + dire[command-1][1]
if 0<=nx<N and 0<=ny<M:
roll(command,nx,ny)
else:
continue
X,Y = nx,ny
print(dice[0])
첫 풀이방식은 문제에 주어진 조건을 그대로 따라 했다.
문제에서 보여준 전개도 대로 실행했다. 일단 크기가 6인 리스트를 만들어 주사위로 지정을 했다.
문제에서 보여준 전개도에서 각 위치에 해당하는 값은 전개도에 있는 값의 -1에 인덱스에 저장을 했다.
즉 정 가운데는 0번 인덱스, 3번 위치에 있는것은 2번 인덱스에 저장을 했다.
이런식으로 주사위를 가정하고, 주사위를 동서남북으로 돌렸을때, 인덱스가 바뀌는 위치를 계산해줬다. 그리고 동서남북에 따라, 주사위가 바뀌는 것을 구현해주었다.
동서남북명령어가 1,2,3,4로 들어오니 그에 맞춰 이동값을 dire에 저장해줬다. 그 다음에는 명령어를 실행시켜주는 반복문을 하고, 범위를 벗어나는 경우에는 아무것도 출력을 하면 안되니 범위를 벗어나는 경우에는 continue로 넘어가준다. 그렇지 않을 때에는, roll이라는 함수를 실행시켜 주사위를 굴리고, 그 위치에 존재하는 값에 따라 문제에 주여진 조건대로 실행시켰다.
하지만 이렇게 풀고난뒤 한가지 불만점이 있었는데, 각 케이스마다 전부 하나하나 인덱스를 바꿔주는 로직이 마음에 들지 않았다.
그래서 개선한 코드는 다음과 같다.
# 14499 주사위 굴리기
# N*M 지도
# 주사위는 윗면이 1 동쪽방향이 3인 상태로 놓아진다.
def roll(direction,nx,ny):
global dice,map_list,moving_dice
dice[0],dice[-1],dice[moving_dice[direction][0]],dice[moving_dice[direction][1]] = dice[moving_dice[direction][0]],dice[moving_dice[direction][1]],dice[-1],dice[0]
if map_list[nx][ny]:
dice[5] = map_list[nx][ny]
map_list[nx][ny] = 0
else:
map_list[nx][ny] = dice[5]
N,M,X,Y,K = map(int,input().split())
map_list = [list(map(int,input().split())) for _ in range(N)]
# [1,2,3,4,5,6]
# 동쪽 1 [4,2,1,6,5,3]
# Top,Bottom,바뀔것1,바뀔것2 = 바뀔것1,바꿀것2,bottm,top
# 서쪽 2 [3,2,6,1,5,4]
# 북쪽 3 [5,1,3,4,6,2]
# 남쪽 4 [2,6,3,4,1,5]
dice = [0]*6
dire = [(0,1),(0,-1),(-1,0),(1,0)]
moving_dice = {1 : [3,2],2:[2,3],3:[4,1],4:[1,4]}
command_list = list(map(int,input().split()))
for command in command_list:
nx = X + dire[command-1][0]
ny = Y + dire[command-1][1]
if 0<=nx<N and 0<=ny<M:
roll(command,nx,ny)
else:
continue
X,Y = nx,ny
print(dice[0])
나머지 로직은 전부 동일하지만, 주사위가 굴러갈때의 규칙성이 있다.
규칙은 다음과 같다.
주사위는 총 6면이 있고, 서로 마주보는걸로 묶을시 3쌍으로 볼수 있다. 주사위를 굴릴 시, 우리가 굴리기전의 Top,bottom 한 쌍과 주사위를 굴러오서 오는 한쌍이 위치가 바뀌고 나머지 한쌍은 그대로 위치한다.
Prev -- >> Next
굴렸을때 Top에 가는 거 Top
굴렸을때 Bottom에 가는 거 Bottom
Top Prev에서 굴렸을때 Bottom에 가는것이 있었던 위치
Bottom Prev에서 굴렸을때 Top에 가는 것이 있었던 위치
글로 설명하기 좀 힘든데 이러한 특징점을 가지고 있따. 그러므로 각 명령어마다, 바뀌는 Index값을 Dictionary에 저장해놓고, 위의 걸 구현해주었다.
같은 코드를 여러번 반복하는 것을 막을 수 있었다. 당연히 실전에서는 위의 풀이방식대로 풀 것 같다.