Baekjoon Review

[Gold 5] 1106 호텔

hanseongbugi 2024. 3. 8. 18:17

https://www.acmicpc.net/problem/1106

 

1106번: 호텔

첫째 줄에 C와 형택이가 홍보할 수 있는 도시의 개수 N이 주어진다. C는 1,000보다 작거나 같은 자연수이고, N은 20보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에는 각 도시에서 홍보할 때

www.acmicpc.net

 

이 문제는 배낭을 활용해서 해결할 수 있다.

 

배낭은 호텔에서 수용가능한 인원의 크기 만큼 담아야 한다.

호텔에서 수용가능한 인원의 크기는 최대 인원 수 * 최대 홍보 비용 이다.

왜냐하면 N개의 도시에 대해 최소 비용인 C원 만큼 고객을 만들어야하기 때문이다.

DP[i] = 돈을 i원 만큼 사용했을 때 최대 확보 고객이라고 한다면

C는 최대 1000이며, 도시를 홍보할 때 드는 비용은 최대 100이다.

100의 돈을 사용했을 때 1명의 고객을 확보할 수 있다면, 100 * 1000인 100000의 크기의 DP 배열이 필요하다.

 

12 2
3 5
1 1

 

위 경우가 입력으로 들어왔다면, 1원부터 X원 까지 최대 고객을 알아봐야한다.

1 2 3 4 5 6 7 8
1 2 5 6 7 10 11 12

위 표처럼 최대 고객이 만들어 진다.

 

점화식을 새워본다면 사용할 수 있는 금액과 입력으로 들어온 홍보 비용 값과 나누어 떨어긴 경우와 

사용할 수 있는 금액과 입력으로 들어온 홍보 비용의 차이가 0보다 클때로 나누어 볼 수 있다.

 

나누어 떨어지는 경우는 홍보 비용을 연속으로 사용할 수 있다는 의미이다.

즉, 입력을 예로 든다면 3의 홍보 비용을 연속으로 2번 사용하여 DP[6]에 2 * 5 을 넣는다는 의미이다.

DP[X] = MAX(이전에 구했던 DP 값, (현재 사용할 금액 / 홍보 비용) * 도시 인원 수)

 

0보다 클때는 홍보 비용을 사용할 수는 있지만 연속으로 사용하는 것이 아니라는 의미이다.

즉, 입력으로 예를 든다면 현재 홍보 비용의 인원 수와 과거에 구한 인원수를 더하는 것이다. DP[7] = DP[6] + 1

DP[X] = MAX(이전에 구했던 DP 값, DP[현재 사용할 금액 - 홍보 비용] + 도시 인원 수)

현재 사용할 금액에서 홍보 비용을 빼는 이유는 DP[7]일 때 3인 경우 6원에서 오는 것이 아닌 4원에서 값을 누적 시켜야 하기 때문이다.

 

#include<iostream>
#include<cstring>
using namespace std;

int C, N;
pair<int,int> arr[21];
int dp[100001];

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	
    cin>> C >> N;
    
    for(int i = 0;i<N;i++)
        cin>>arr[i].first>>arr[i].second;

    
    for(int i = 1;i<=100000;i++){
       for(int j = 0;j<N;j++){
            if(i%arr[j].first == 0){
                dp[i] = max(dp[i], (i/arr[j].first)*arr[j].second);
            }
            if(i-arr[j].first >= 0){
                dp[i] = max(dp[i], dp[i-arr[j].first] + arr[j].second);
            }
       }
       if(C<=dp[i]){
            cout<<i<<'\n';
            break;
       }
    }
    
    
    return 0;
}