1106번: 호텔
첫째 줄에 C와 형택이가 홍보할 수 있는 도시의 개수 N이 주어진다. C는 1,000보다 작거나 같은 자연수이고, N은 20보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에는 각 도시에서 홍보할 때
www.acmicpc.net
어렵사리 냅색과 DP라는 생각을 떠올렸는데도 해결을 못 했었다;;
계속해서 DP를 시도하다가 재귀로 시도하여 통과했다.
재귀 부분 설명
배열의 인덱스는 유치한 고객 수이며 값은 비용이다.
하나의 도시를 0개부터 최대한으로 선택하는 경우까지 모두 비교.
최대한으로 선택하는 경우는 해당 도시 고객만으로 유치해야 할 고객을 넘어서는 시점으로 설정.
- 해당 도시에 N배를 투자했는데도 유치해야할 고객 수와 같거나 그에 미치지 못한다면
- (현재까지의 비용 + 해당 도시의 비용 * N) 이 배열의 (현재 고객 수 + 해당 도시의 고객 * N) 번째의 비용보다 작다면
- 배열을 업데이트하고 다음 도시를 선택하도록 재귀
- 해당 도시에 N배 투자했을 때 유치해야할 고객 수 보다 고객이 많아진 경우
- (현재까지의 비용 + 해당 도시의 비용 * N)의 비용이 c명을 유치했을 때 드는 비용보다 작다면
- 배열을 업데이트
- 해당 도시에 더 투자하는 경우는 고려 X
(해당 도시에 N배 투자했을 때 유치해야할 고객 수를 넘겼기 때문에 (N + 1) 배 투자하는 경우는 고려할 필요 X)
- (현재까지의 비용 + 해당 도시의 비용 * N)의 비용이 c명을 유치했을 때 드는 비용보다 작다면
코드
#include <iostream>
int c = 0;
int n = 0;
int info[21][2];
long long dp[1001];
void sol(int customer, int cost, int index) {
for (int i = index; i < n; i++) {
for (int j = 0; j < c / info[i][1] + 2; j++) {
if (customer + info[i][1] * j <= c){
if (cost + info[i][0] * j < dp[customer + info[i][1] * j]) {
dp[customer + info[i][1] * j] = cost + info[i][0] * j;
sol(customer + info[i][1] * j, cost + info[i][0] * j, index + 1);
}
} else {
if (cost + info[i][0] * j < dp[c]) {
dp[c] = cost + info[i][0] * j;
}
break;
}
}
}
}
int main()
{
std::cin.tie(NULL);
std::cout.tie(NULL);
std::ios::sync_with_stdio(false);
std::cin >> c >> n;
for (int i = 0; i < n; i++) {
int cost = 0, customer = 0;
std::cin >> cost >> customer;
info[i][0] = cost;
info[i][1] = customer;
}
for (int i = 0; i < 1001; i++) {
dp[i] = 200000000;
}
sol(0, 0, 0);
std::cout << dp[c] << "\n";
return 0;
}
'PS > BOJ' 카테고리의 다른 글
BOJ 16202 : MST 게임 [C++] (0) | 2024.01.31 |
---|---|
BOJ 16206 : 롤케이크 [C++] (0) | 2024.01.30 |
BOJ 17144 : 미세먼지 안녕! [C++] (0) | 2023.01.12 |
BOJ 17070 : 파이프 옮기기 1 [C++] (0) | 2023.01.11 |
BOJ 15686 : 치킨 배달 [C++] (0) | 2023.01.09 |