이동식 저장소

1311. 할 일 정하기 1 본문

Problem Solving/BOJ

1311. 할 일 정하기 1

해스끼 2022. 10. 20. 12:12

단계별로 풀어보기 따라가는 중.

 

1311번: 할 일 정하기 1

N명의 사람과 N개의 일이 있다. 각 사람은 일을 하나 담당해야 하고, 각 일을 담당하는 사람은 한 명 이어야 한다. 또한, 모든 사람은 모든 일을 할 능력이 있다. 사람은 1번부터 N번까지 번호가 매

www.acmicpc.net


$N$명의 사람과 $N$개의 일이 있다. $i$번 사람이 $j$번 일을 할 때의 비용 $D[i][j]$가 주어질 때, 비용을 최소로 하면서 각 사람에게 하나의 일을 할당해 보자.

 

딱 봐도 dp이고, 선택된 일의 집합을 표현해야 하므로 비트마스크 dp를 적용할 수 있다. 마침 $N$이 20으로 매우 작기도 하고.

 

현재 남아있는 일의 집합을 $j$(비트마스크)일 때 $i$번 사람에게 일을 할당하여 얻을 수 있는 비용의 최솟값을 $dp[i][j]$로 정의할 수 있다. 수식으로 표현하면 다음과 같다.

 

$dp[i][j] = \min(D[i][work] + dp[i+1][j - 2^{work}]) ~\forall~ work \in j$

 

그런데 더 빠르게 풀 수도 있다. 위의 식을 대부분 DFS DP로 구현할 텐데, DFS에서 $i$는 항상 1씩 증가하므로 굳이 $dp$에 $i$를 포함할 필요가 없다. 정확히는 상태 집합에 $i$를 포함할 필요는 없다는 말이다.

 

따라서 상태 집합은 남아있는 일의 집합 $j$만으로 충분하다. 의사코드는 다음과 같다.

// depth: 일을 할당할 사람의 번호
// bitmask: 현재 남아있는 일의 집합 (비트마스크)
solve(depth, bitmask):
    if bitmask < 0:
        return INF
    if depth == 0:
        return 0
    
    if dp[bitmask] != -1:
        return dp[bitmask]
    
    for work in j:
        ret = min(D[depth][work] + solve(depth+1, bitmask - (1 << work)))
    dp[bitmask] = ret
    return ret

 


이걸로 solved.ac 플1 달성.

번외: $N$이 커지면?

$N$이 50만 돼도 비트마스크를 쓸 수 없다. 예를 들어 이런 문제는 어떻게 풀어야 할까?

 

14216번: 할 일 정하기 2

N명의 사람과 N개의 일이 있다. 각 사람은 일을 하나 담당해야 하고, 각 일을 담당하는 사람은 한 명 이어야 한다. 또한, 모든 사람은 모든 일을 할 능력이 있다. 사람은 1번부터 N번까지 번호가 매

www.acmicpc.net

Hungarian Algorithm을 사용하면 $O(N^{3})$ 시간에 해결할 수 있다. 한번 공부해 봐야겠다.

Comments