728x90
https://www.acmicpc.net/problem/4991
4991번: 로봇 청소기
각각의 테스트 케이스마다 더러운 칸을 모두 깨끗한 칸으로 바꾸는 이동 횟수의 최솟값을 한 줄에 하나씩 출력한다. 만약, 방문할 수 없는 더러운 칸이 존재하는 경우에는 -1을 출력한다.
www.acmicpc.net
해당문제는 다이나믹프로그래밍, 비트마스킹, 완전탐색, 깊이우선탐색, 너비우선탐색을 활용하여 문제를 해결 하였습니다.
너비우선탐색으로는 0과 *, *과* 사이의 거리를 구하였고, dp 테이블에 각각의 사이를 메모리제이션 하였습니다.
완전탐색과 깊이우선탐색, 비트마스킹으로 모든 경우의수를 방문 합니다.
from sys import stdin
from collections import deque
input = stdin.readline
move = [(0, 1), (0, -1), (1, 0), (-1, 0)]
INF = int(10e9)
def dfs(startidx, visited, cost):
if cost > minvalue:
return INF
if visited == (1 << len(dirtylist)) - 1: # 모든 곳을 방문했다면
return cost
min_cost = INF
for endidx in range(len(dirtylist)):
if not visited & (1 << endidx):
new_visited = visited | (1 << endidx)
new_cost = cost + bfs(startidx, endidx)
min_cost = min(min_cost, dfs(endidx, new_visited, new_cost))
return min_cost
def bfs(startidx, endidx): # start 부터 end 까지 최소거리 탐색 , 만약 가지 못한다면 INF
if dp[startidx][endidx] != None:
return dp[startidx][endidx]
visited = [[False for _ in range(w)] for _ in range(h)]
queue = deque()
y, x = dirtylist[startidx]
end_y, end_x = dirtylist[endidx]
queue.append([y, x, 0])
while queue:
i, j, cost = queue.popleft()
for dy, dx in move:
ny = dy + i
nx = dx + j
if h > ny >= 0 and w > nx >= 0 and not visited[ny][nx] and not graph[ny][nx] == 'x':
visited[ny][nx] = True
if ny == end_y and nx == end_x:
dp[startidx][endidx] = cost + 1
return dp[startidx][endidx]
queue.append([ny, nx, cost + 1])
dp[startidx][endidx] = INF
return dp[startidx][endidx]
while True:
w, h = map(int, input().split()) # 너비, 높이
if w == 0 and h == 0: # 0,0이 주어지면 종료한다.
break
else:
graph = []
dirtylist = []
start = 0
for i in range(h):
char = list(map(str, input()))
for j in range(len(char)):
if char[j] == '*' or char[j] == 'o':
dirtylist.append([i, j])
if char[j] == 'o':
start = len(dirtylist) - 1
graph.append(char)
minvalue = INF
dp = [[None for _ in range(len(dirtylist))] for _ in range(len(dirtylist))]
for endidx in range(len(dirtylist)):
visited = 1 << start
if not visited & (1 << endidx):
visited |= 1 << endidx
minvalue = min(minvalue, dfs(endidx, visited, bfs(start, endidx)))
if minvalue != INF:
print(minvalue)
else:
print(-1)
728x90
'알고리즘 > 백준' 카테고리의 다른 글
[백준] 1011번 : Fly me to the Alpha Centauri (0) | 2023.07.30 |
---|---|
[백준] 2573번 : 빙산 (0) | 2023.07.30 |
[백준] 1194번 : 달이 차오른다, 가자. (0) | 2023.07.29 |
[백준] 1806번 : 부분합 (0) | 2023.07.26 |
[백준] 2098번 : 외판원 순회 (0) | 2023.07.26 |