BOJ 1311 할 일 정하기 1
BOJ 1311 할 일 정하기 1
https://www.acmicpc.net/problem/1311
문제
N명의 사람과 N개의 일이 있다. 각 사람은 일을 하나 담당해야 하고, 각 일을 담당하는 사람은 한 명 이어야 한다. 또한, 모든 사람은 모든 일을 할 능력이 있다.
사람은 1번부터 N번까지 번호가 매겨져 있으며, 일도 1번부터 N번까지 번호가 매겨져 있다.
$D_{ij}$를 i번 사람이 j번 일을 할 때 필요한 비용이라고 했을 때, 모든 일을 하는데 필요한 비용의 최솟값을 구하는 프로그램을 작성하시오.
입력
첫째 줄에 사람과 일의 수 N (1 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에는 D의 내용이 주어진다. 비용은 10,000보다 작거나 같은 자연수이다.
출력
모든 일을 하는데 필요한 비용의 최솟값을 출력한다.
예제 입력 1
3 2 3 3 3 2 3 3 3 2
예제 출력 1
6
코드
기본적인 접근 방법은 DFS 였고 비트마스킹으로 표현한 메모이제이션을 활용해 쉽게 풀 수 있었다.
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
static int N, fullBits;
static int[][] D, dp;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
fullBits = (1 << N) - 1;
D = new int[N][N];
/**
* dp의 첫 번째 인덱스는 사람의 번호를 의미하고,
* 두 번째 인덱스는 비트마스크로 표현한 남아있는 일을 의미한다.
* 즉, dp[i][bitmask]는 i번째 사람이 bitmask 같이 일이 남아있는 상태에서 드는 최소 비용을 의미한다.
*/
dp = new int[N][1 << N];
for (int i = 0; i < N; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
for (int j = 0; j < N; j++)
D[i][j] = Integer.parseInt(st.nextToken());
}
// 첫 번째 사람이 할 일을 선택하지 않았을 때부터 시작
System.out.println(dfs(0, 0));
}
static int dfs(int person, int bitmask) {
// 모두 각자 할 일을 찾았으면 남은 일이 없으므로 이 때 드는 비용은 0이다.
if(bitmask == fullBits) return 0;
if(dp[person][bitmask] != 0) return dp[person][bitmask];
dp[person][bitmask] = Integer.MAX_VALUE;
for (int i = 0; i < N; i++) {
// 현재 검사 중인 사람이 i번째 일을 수행했을 때 드는 최소 비용을 계산한다.
if((bitmask & 1 << i) == 0)
dp[person][bitmask] = Integer.min(
dp[person][bitmask],
dfs(person + 1, bitmask | 1 << i) + D[person][i]
);
}
return dp[person][bitmask];
}
}
This post is licensed under CC BY 4.0 by the author.