칸마다 비용이 다른 N x N 크기의 화단에서 3개의 꽃을 피울 수 있는 최소 비용을 구하는 문제다.
꽃은 심은 칸을 기준으로 상하, 좌우로 잎이 피며 서로 다른 꽃이 만나거나 화단 밖으로 나가지 않아야 한다.
import sys
read = sys.stdin.readline
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]
N = int(read())
ground = [list(map(int, read().split())) for _ in range(N)]
cost = [[0] * (N-2) for _ in range(N-2)]
for y in range(1, N-1):
for x in range(1, N-1):
cost[y-1][x-1] = ground[y][x]
for i in range(4):
nx = x + dx[i]
ny = y + dy[i]
cost[y-1][x-1] += ground[ny][nx]
result = sys.maxsize
visited = [[False] * N for _ in range(N)]
def isValid(x, y):
if visited[y][x]:
return False
for i in range(4):
nx = x + dx[i]
ny = y + dy[i]
if visited[ny][nx]:
return False
return True
def setVisited(x, y, check):
visited[y][x] = check
for i in range(4):
nx = x + dx[i]
ny = y + dy[i]
visited[ny][nx] = check
def dfs(depth, total):
global result
if total >= result:
return
if depth == 3:
result = min(result, total)
return
for y in range(1, N-1):
for x in range(1, N-1):
if isValid(x, y):
setVisited(x, y, True)
dfs(depth + 1, total + cost[y-1][x-1])
setVisited(x, y, False)
dfs(0, 0)
print(result)
cost
에 미리 저장한다.isValid
: 해당 칸에 씨앗을 심을 수 있는 지 판단하는 함수다.False
를 반환한다.setVisited
: 탐색을 하며 꽃을 심거나 없앨 때 꽃의 유무를 설정하는 함수다.True
로, 꽃을 없앨 땐 False
로 설정한다.depth
: 현재까지 심은 꽃의 수, total
: 현재까지의 비용total
(지금까지 계산한 비용)이 result
(현재까지의 최솟값)보다 크면 탐색을 중단하고 돌아간다. (가지치기)result
를 total
과 비교해 더 작은 값으로 업데이트 한다.