일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- TEST
- Python
- 암호학
- Rxjava
- 코드포스
- 쿠링
- textfield
- MiTweet
- pandas
- architecture
- livedata
- ProGuard
- androidStudio
- Compose
- Hilt
- Gradle
- 백준
- AWS
- Kotlin
- activity
- relay
- 코루틴
- 프로그래머스
- Codeforces
- MyVoca
- android
- Coroutine
- boj
- GitHub
- Coroutines
- Today
- Total
이동식 저장소
1311. 할 일 정하기 1 본문
단계별로 풀어보기 따라가는 중.
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})$ 시간에 해결할 수 있다. 한번 공부해 봐야겠다.
'Problem Solving > BOJ' 카테고리의 다른 글
1445. 일요일 아침의 데이트 (0) | 2022.11.29 |
---|---|
19582. 200년간 폐관수련했더니 PS 최강자가 된 건에 대하여 (0) | 2022.11.23 |
10999. 구간 합 구하기 2 (0) | 2022.10.11 |
11562. 백양로 브레이크 (0) | 2022.10.04 |
2248. 이진수 찾기 (0) | 2022.09.18 |