Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- Spring
- SWEA
- 트라이
- 우선순위큐
- 로봇 청소기
- 2021 KAKAO BLIND RECRUITMENT
- 크루스칼
- BFS
- 이분탐색
- 구현
- 파이썬
- 백트래킹
- 시뮬레이션
- 브루트포스
- 조합
- 2020 KAKAO BLIND RECRUITMENT
- 투 포인터
- 비트마스킹
- 백준
- 2018 KAKAO BLIND RECRUITMENT
- 플로이드 와샬
- 투포인터
- 2019 KAKAO BLIND RECRUITMENT
- 플로이드와샬
- 2020 카카오 인턴십
- 스택
- 다익스트라
- 최소 신장 트리
- GIT
- 프로그래머스
Archives
- Today
- Total
개발조아
[BOJ/백준] 16985 Maaaaaaaaaze 파이썬 본문
728x90
문제 링크 : https://www.acmicpc.net/problem/16985
이동 조건을 잘못이해해서 헤맸던 문제이다. 입구에서 이동할 때 바깥 면에 있는 칸으로만 이동이 된다고 이해해서 예제 입력 3번부터 답이 이상했다. 근데 알고보니 그냥 3차원 BFS 바깥면 상관없이다 모든 칸으로 이동이 가능한거였다.
문제는 순열+배열회전+BFS인데 크게 어려운건 없다고 생각했다.
주어진 판의 순서를 섞고 각 판을 회전하여 조합을 만든 후 BFS로 최단거리를 구하면 되는 문제이다.
판 섞는 것은 itertools의 permutations 메소드로 아주 편하게 생성했다.
0~4까지 숫자에서 5개를 가지고 순열을 생성하여 order에 저장했고, 꼭대기는 몇번 판, 그 밑은 몇번판 이런식으로 저장된다.
이후 order 순서대로 배열을 회전하였다.
회전은 tmp 배열 하나 만들어서 거기에 원본 값 넣고 끝에부터 회전하여 원본배열에 다시 저장했다.
그림처럼 tmp의 row를 원본 배열의 col으로 넣어주면 된다.
인덱스만 잘 조절하면 돼서 어렵지 않게 할 수 있다.
tmp[x][y]를 원본[y][4-x]에 넣어주면 된다.
5번째 판까지 회전을 했다면 BFS를 돌리면 된다.
BFS는 3차원 공간에서하는 평범한 BFS이지만 시작 위치를 잘 조정해야한다.
그치만 이마져도 [0,0,0]에서 시작 [4,4,4]에서 끝 으로 하면 된다.
어차피 시작과 끝 판을 회전하면 모든 경우를 다 볼 수 있기 때문에 하나로 고정해도 된다.
from sys import stdin
from itertools import permutations
from collections import deque
input = stdin.readline
dx = [-1,1,0,0,0,0]
dy = [0,0,-1,1,0,0]
dz = [0,0,0,0,-1,1]
INF = 9876543210
board = [[list(map(int, input().split())) for _ in range(5)] for _ in range(5)]
visited = [[[0] * 5 for _ in range(5)] for _ in range(5)]
visited_num = 0
answer = INF
def solv():
for order in permutations(range(5),5):
stack_board(order,0)
print(answer if answer != INF else -1)
def stack_board(order,idx):
global board
if answer == 12:
return
if idx == 5:
simul(order)
return
for _ in range(4):
board_rotate(order[idx])
stack_board(order,idx+1)
def simul(order):
global answer,visited,visited_num
game_board = []
for idx in order:
game_board.append(board[idx])
visited_num += 1
start = [0,0,0]
end = [4,4,4]
if game_board[start[0]][start[1]][start[2]] != 1 or game_board[end[0]][end[1]][end[2]] != 1:
return
visited_num += 1
q = deque([start+[0]])
visited[0][start[0]][start[1]] = visited_num
while q:
z,x,y,cnt = q.pop()
if cnt >= answer:
continue
if end[0] == z and end[1] == x and end[2] == y:
answer = min(answer,cnt)
break
for d in range(6):
nz = z + dz[d]
nx = x + dx[d]
ny = y + dy[d]
if point_validator(nz,nx,ny,game_board):
visited[nz][nx][ny] = visited_num
q.appendleft((nz,nx,ny,cnt+1))
def point_validator(z,x,y,game_board):
if z < 0 or x < 0 or y < 0 or z >= 5 or x >= 5 or y >= 5:
return False
elif game_board[z][x][y] == 0:
return False
elif visited[z][x][y] == visited_num:
return False
return True
def board_rotate(z):
global board
tmp = []
for row in board[z]:
tmp_row = []
for num in row:
tmp_row.append(num)
tmp.append(tmp_row)
for x in range(5):
for y in range(5):
board[z][y][4-x] = tmp[x][y]
solv()
'알고리즘 > 백준' 카테고리의 다른 글
[BOJ/백준] 1325 효율적인 해킹 파이썬 (0) | 2021.08.22 |
---|---|
[BOJ/백준] 18808 스티커 붙이기 파이썬 (0) | 2021.08.20 |
[BOJ/백준] 2116 주사위 쌓기 파이썬 (0) | 2021.08.19 |
[BOJ/백준] 9934 완전 이진 트리 파이썬 (0) | 2021.08.19 |
[BOJ/백준] 12904 A와 B 파이썬 (0) | 2021.08.18 |
Comments