문제


https://www.acmicpc.net/problem/1311


풀이


일을 배정받은 사람 정보와 배정된 일의 정보 각각을 비트마스크로 관리하면 DP 테이블의 크기가 2 ** 40으로 TLE를 받는다.

외판원 순회 문제도 그렇고 N * 2 ** N 크기의 DP 테이블을 자주 봤으니 끼워 맞춰보자.

1번 사람부터 차례로 일을 배정하거나, 1번 일부터 차례로 배정시키면 해결된다.

그런데 2 * 2 ** N 크기의 DP 테이블 + Bottom-Up 방식으로 문제를 풀 수 있다.

dp[사람_mask]에 [결과, 일_mask] 이런 식으로 담으면 가능하다.


코드


import sys

n = int(sys.stdin.readline())
board = [list(map(int, sys.stdin.readline().split())) for _ in range(n)]
dp = [(0, 0)] * 2 ** n

for k in range(1, 2 ** n):
    res = float('inf')
    mask = 0
    for i in range(n):
        if k & (1 << i):
            temp, sub_mask = dp[k | (1 << i)]
            sub_res = float('inf')
            idx = 0
            for j in range(n):
                if (not sub_mask & (1 << j)) and (sub_res > board[i][j]):
                    sub_res = board[i][j]
                    idx = j

            sub_res += temp
            sub_mask |= (1 << idx)

            if res > sub_res:
                res = sub_res
                mask = sub_mask

    dp[k] = (res, mask)

print(dp[-1][0])

Leave a comment