https://www.acmicpc.net/problem/1311
외판원 문제를 풀때는 dp + 비트마스킹에 적응을 못했어서 푸는데 어려움이 많았지만 이번 문제는 좀 수월하게 했던것 같습니다..
dp[x][cost] : x번 사람이 고를 때 x - 1번째 사람까지 골랐던 일의 상태가 cost인 비용의 최솟값
여기서 cost에 비트마스킹을 이용합니다. (N = 20이므로 약 100만 정도의 크기입니다.)
저는 번호를 0 ~ N - 1로 두었기때문에 0번 사람부터 차례로 0 ~ N - 1번 일까지 돌면서 고르지 않은 일만 선택하였고,
x가 N일 때 모든 사람이 일을 골랐으면 0, 아니면 INF을 리턴하였습니다.
+ 음.. 시간과 메모리가 적게 나온 분의 풀이를 보았는데 dp[x][cost]가 아닌 dp[cost]만으로도 해결이 됐습니다..
dp[cost] : 고른 일의 상태가 cost일 때 비용의 최솟값
으로 두고 해결하면 될 것 같습니다! (소스는 같이 올리겠습니다)
역시 1차원 배열로 한 것이 시간적으로나 메모리적으로나 많은 이득을 가져갑니다..
[2차원 배열]
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
49
|
#include <iostream>
#include <cstring>
#include <algorithm>
#define MAX 20
#define INF 1000000000
using namespace std;
int list[MAX][MAX], dp[MAX][1 << MAX];
int N, chk;
int func(int x, int cost) {
if (x == N) {
if(cost == chk) return 0;
else return INF;
}
int &ret = dp[x][cost];
if (ret != -1) return ret;
ret = INF;
for (int i = 0; i < N; i++) {
if (cost & (1 << i)) continue;
ret = min(ret, func(x + 1, cost | (1 << i)) + list[x][i]);
}
return ret;
}
void input() {
cin >> N;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
cin >> list[i][j];
}
}
memset(dp, -1, sizeof(dp));
chk = (1 << N) - 1;
}
int main() {
cin.tie(NULL); cout.tie(NULL);
ios::sync_with_stdio(false);
input();
cout << func(0, 0) << '\n';
return 0;
}
|
cs |
[1차원 배열]
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
49
|
#include <iostream>
#include <cstring>
#include <algorithm>
#define MAX 20
#define INF 1000000000
using namespace std;
int list[MAX][MAX], dp[1 << MAX];
int N, chk;
int func(int x, int cost) {
if (x == N) {
if(cost == chk) return 0;
else return INF;
}
int &ret = dp[cost];
if (ret != -1) return ret;
ret = INF;
for (int i = 0; i < N; i++) {
if (cost & (1 << i)) continue;
ret = min(ret, func(x + 1, cost | (1 << i)) + list[x][i]);
}
return ret;
}
void input() {
cin >> N;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
cin >> list[i][j];
}
}
memset(dp, -1, sizeof(dp));
chk = (1 << N) - 1;
}
int main() {
cin.tie(NULL); cout.tie(NULL);
ios::sync_with_stdio(false);
input();
cout << func(0, 0) << '\n';
return 0;
}
|
cs |
'algorithm > dp' 카테고리의 다른 글
boj 1648 격자판 채우기 (0) | 2021.06.22 |
---|---|
boj 14700 넴모넴모 (Hard) (0) | 2021.06.22 |
boj 1577 도로의 개수 (0) | 2021.06.20 |
boj 4781 사탕 가게 (0) | 2021.06.19 |
boj 2186 문자판 (0) | 2021.06.19 |