[BaekJoon] #1106 - 호텔 [Java][C++]
[BaekJoon] #1106 - 호텔 [Java][C++]
1. 아이디어
일종의 무한 배낭 문제로 $C$명 이상 확보할 수 있는 최소 비용을 찾아야 하는 문제다. 배낭을 고객으로 가치를 비용으로 설정한 배낭에서 배낭 크기가 $C$ 이상인 상황 중 배낭 가치가 최소일 때를 찾으면 된다. 이때 정확히 $C$명을 찾았을 때 비용이 최소가 아니라 $C$명보다 큰 어느 순간 비용이 최소일 수 있다는 점에 주의해야 한다.
최소 비용을 갱신하며 다이나믹 프로그래밍을 해야 하므로 초기엔 최댓값으로 초기화한 후 갱신을 해나가면 된다. 고객 한 명의 최대 비용이 100이므로 최대 1,000명 이상 확보하는 비용이 100,000을 넘을 수 없다. dp 테이블을 전부 갱신했다면 $C$명부터 $C + 100$명까지 중 최소 비용을 찾아서 출력하면 된다.
2. 복잡도
| 접근 | 시간 | 공간 |
|---|---|---|
| 배열 DP | $O(N \times C)$ | $O(N \times C)$ |
| 공간 최적화 DP | $O(N \times C)$ | $O(N + C)$ |
($N$ = 입력값 n, $C$ = 입력값 c)
3. 코드
풀이 1: 배열 DP [Java][C++]
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
import java.io.*;
import java.util.*;
public class Main {
static final int INF = 100000;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int c = Integer.parseInt(st.nextToken());
int n = Integer.parseInt(st.nextToken());
int[] costs = new int[1 + n];
int[] people = new int[1 + n];
for (int i = 1; i <= n; i++) {
st = new StringTokenizer(br.readLine());
costs[i] = Integer.parseInt(st.nextToken());
people[i] = Integer.parseInt(st.nextToken());
}
int[][] dp = new int[1 + n][1 + c + 100];
Arrays.fill(dp[0], 1, dp[0].length, INF);
for (int i = 1; i <= n; i++) {
int cost = costs[i];
int person = people[i];
for (int j = 1; j <= c + 100; j++) {
if (j < person) {
dp[i][j] = dp[i - 1][j];
} else {
dp[i][j] = Math.min(dp[i][j - person] + cost, dp[i - 1][j]);
}
}
}
int min = INF;
for (int j = c; j <= c + 100; j++) {
min = Math.min(min, dp[n][j]);
}
System.out.println(min);
}
}
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
#include <bits/stdc++.h>
using namespace std;
const int INF = 100000;
int dp[1 + 20][1 + 1100];
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int c, n;
cin >> c >> n;
vector<pair<int, int>> a(n);
for (auto& [cost, person] : a) cin >> cost >> person;
fill(dp[0] + 1, dp[0] + 1101, INF);
for (int i = 1; i <= n; i++) {
auto [cost, person] = a[i - 1];
for (int j = 1; j <= c + 100; j++) {
if (j < person) {
dp[i][j] = dp[i - 1][j];
} else {
dp[i][j] = min(dp[i][j - person] + cost, dp[i - 1][j]);
}
}
}
int mn = INF;
for (int j = c; j <= c + 100; j++) {
mn = min(mn, dp[n][j]);
}
cout << mn;
}
풀이 2: 공간 최적화 DP [Java][C++]
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
import java.io.*;
import java.util.*;
public class Main {
static final int INF = 100000;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int c = Integer.parseInt(st.nextToken());
int n = Integer.parseInt(st.nextToken());
int[] costs = new int[n];
int[] people = new int[n];
for (int i = 0; i < n; i++) {
st = new StringTokenizer(br.readLine());
costs[i] = Integer.parseInt(st.nextToken());
people[i] = Integer.parseInt(st.nextToken());
}
int[] dp = new int[1 + c + 100];
Arrays.fill(dp, 1, dp.length, INF);
for (int i = 0; i < n; i++) {
int cost = costs[i];
int person = people[i];
for (int j = person; j <= c + 100; j++) {
dp[j] = Math.min(dp[j - person] + cost, dp[j]);
}
}
int min = INF;
for (int j = c; j <= c + 100; j++) {
min = Math.min(min, dp[j]);
}
System.out.println(min);
}
}
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
#include <bits/stdc++.h>
using namespace std;
const int INF = 100000;
int dp[1 + 1100];
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int c, n;
cin >> c >> n;
vector<pair<int, int>> a(n);
for (auto& [cost, person] : a) cin >> cost >> person;
fill(dp + 1, dp + 1101, INF);
for (auto [cost, person] : a) {
for (int j = person; j <= c + 100; j++) {
dp[j] = min(dp[j - person] + cost, dp[j]);
}
}
int mn = INF;
for (int j = c; j <= c + 100; j++) {
mn = min(mn, dp[j]);
}
cout << mn;
}
This post is licensed under CC BY 4.0 by the author.