레야몬
[C++] 1311번 할 일 정하기 1 - DP, 비트마스킹, 비트필드를 이용한 DP 본문
1. 문제
- N명의 사람과 N개의 일이 있다. 각 사람은 일을 하나 담당해야 하고, 각 일을 담당하는 사람은 한 명이다. 또한 모든 사람은 모든 일을 할 능력이 있다.
- 사람과 일은 1~N까지 번호가 매겨져 있다.
- 모든 일을 하는데 필요한 비용의 최솟값을 구하자.
<입력>
- - 1 - 사람과 일의 수 \(N(1 \leq N \leq 20)\)
- - N개의 줄 - 비용 \(D(1 \leq D \leq 10,000)\)
<출력>
- 모든 일을 하는데 필요한 비용의 최솟값
2. 재정의
- X
3. 해결 방법
- 비트필드를 이용한 DP 기본 문제
4. 실수한 점, 개선 방법
- 얘는 비트필드를 이용할 때 DP에서 탐색하는 no와 상관없이 dp가 같기 때문에 통일해도 된다.
- 이렇게 푼 다른 사람 코드가 있어서 아래에 링크해두었다.
<코드>
#include <iostream>
using namespace std;
const int MAX_N = 21;
const int INF = 987654321;
// <문제>
// 사람과 일의 수 N
int N;
// 일을 하는데 필요한 비용 D
int D[MAX_N][MAX_N];
// DP
int dp[MAX_N][1 << MAX_N];
void input() {
cin >> N;
for(int i=0; i<N; i++)
for(int j=0; j<N; j++)
cin >> D[i][j];
}
// 비트월드를 이용한 DP
int DP(int now, int visited) {
// 모든 일을 다 배정했을 경우 반환
if(now == N)
return 0;
// 현재 상태를 이미 계산한 값이 dp 테이블에 있다면 그대로 사용
if(dp[now][visited])
return dp[now][visited];
for(int i=0; i<N; i++) {
// 이미 방문한 경우 패스
if(visited & (1 << i))
continue;
// i번 노드 방문 처리 후 최소 비용 반환
int tmp = DP(now+1, visited | 1 << i);
if(dp[now][visited])
dp[now][visited] = min(dp[now][visited], D[now][i] + tmp);
else
dp[now][visited] = D[now][i] + tmp;
//cout << now << ' ' << i << ' ' << dp[now][visited] << ' ' << visited << '\n';
}
// 최소 비용 반환
return dp[now][visited];
}
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
input();
cout << DP(0, 0);
return 0;
}
<참고한 코드 (풀어야 볼 수 있습니다.)>
https://www.acmicpc.net/source/46827763
로그인
www.acmicpc.net
<외판원 순회 문제>
[알고리즘] 외판원 순회 문제
모든 도시들을 단 한번씩만 방문하고 원래 시작점으로 돌아오는 최소 비용을 구해보자!
velog.io
<문제 바로가기>
https://www.acmicpc.net/problem/1311
1311번: 할 일 정하기 1
N명의 사람과 N개의 일이 있다. 각 사람은 일을 하나 담당해야 하고, 각 일을 담당하는 사람은 한 명 이어야 한다. 또한, 모든 사람은 모든 일을 할 능력이 있다. 사람은 1번부터 N번까지 번호가 매
www.acmicpc.net
※현재 고등학교 등교 중인 학생입니다. 이제 알고리즘을 본격적으로 공부하기 시작해서 아직 초보입니다. 혹시 제가 잘못 알고 있는 점이나 더 좋은 풀이 방법이 있어 댓글에 남겨주시면 감사히 하나하나 열심히 읽어보겠습니다. 좋아요, 단순한 댓글 한마디라도 저에겐 큰 힘이 됩니다! 감사합니다.
'알고리즘 > 백준' 카테고리의 다른 글
[C++] 1305번 광고 - KMP, 문자열 (0) | 2022.12.17 |
---|---|
[C++] 5670번 휴대폰 자판 - 자료 구조, 문자열, 트리, 트라이 (0) | 2022.12.16 |
[C++] 7869번 두 원 - 수학, 기하학, 많은 조건 분기 (0) | 2022.12.14 |
[C++] 2162번 선분 그룹 - 자료 구조, 기하학, 분리 집합, 선분 교차 판정 (0) | 2022.12.13 |
[C++] 20149번 선분 교차 3 - 기하학, 많은 조건 분기, 선분 교차 판정 (0) | 2022.12.13 |
Comments