Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 쿠링
- Rxjava
- TEST
- 코드포스
- pandas
- Codeforces
- 백준
- MiTweet
- GitHub
- architecture
- 코루틴
- activity
- Kotlin
- boj
- relay
- textfield
- livedata
- android
- androidStudio
- Coroutine
- Hilt
- Compose
- ProGuard
- 프로그래머스
- Gradle
- 암호학
- Python
- AWS
- MyVoca
- Coroutines
Archives
- Today
- Total
이동식 저장소
1311. 할 일 정하기 1 본문
단계별로 풀어보기 따라가는 중.
$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만 돼도 비트마스크를 쓸 수 없다. 예를 들어 이런 문제는 어떻게 풀어야 할까?
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 |
Comments