코딩/백준 문제 풀이

BOJ 12430 - 생존자

stonejjun 2022. 8. 16. 01:23

문제 링크 : https://www.acmicpc.net/problem/12430

문제 풀이

  문제를 딱 읽으면 DP향이 느껴진다. 냅색 혹은 동전으로 낼 수 있는 가격과 비슷한 느낌이지만, 정확히 허기질 때만 다른 음식을 먹을 수 있다. A[x]를 x일 동안 버틸 수 있는 지를 체크하는 것이라면 i번째 음식은 0~$P_i$ 값을 $S_i ~ P_i + S_i$에 더하는 즉, 업데이트를 하는 효과를 가지고 있다. 

하지만 동전 문제와 다른 점은 한계인 $P_i$가 존재하기 때문에 업데이트하는 순서에 따라서 나오는 결과값이 달라질 것이다. 업데이트 한다는 것은 그 음식을 먹는 가능성을 주는 것이기 때문에 정답 결과가 나오는 경우 때, 음식을 먹는 순서대로 업데이트를 실시한다면 최댓값을 얻어낼 수 있다. 

 그렇다면 최대한 오래 살기 위해서 음식을 어떻게 먹어야 할까? a->b 순서가 b->a 순서 보다 무조건 유리한 조건을 찾으면 된다. a번 음식의 업데이트로 위치가 $S_a$ 만큼 더해지는데, 이 위치가 $P_b$ 이하면 한 번 더 업데이트 할 수 있다. 반대의 경우도 마찬가지이다. 천천히 놓고 생각을 해본다면 $P_a - S_b < P_b - S_a$ 인 경우에 a를 먼저 먹는 것이 무조건 옳다고 할 수 있다. 이를 식 정리를 한다면 $S_a + P_a < S_b - P_b$ 인 경우에 a를 먼저 먹는 것이고, 즉, S+P 에 대해서 정렬을 하면 되는 것이다. 단 2개만 아닌 N개 모두 정렬해도 되는 이유는 exchange arguments의 힘을 빌리면 알 수 있다. 

 시간 복잡도는 O(NP)가 되어서 아슬아슬하다고 느낄 수 있으나, 10초의 제한 시간을 보고 오히려 이 풀이가 맞다는 확신을 가질 수 있다. 

코드

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef double dl;
typedef pair<dl,dl> pdi;
typedef pair<ll,ll> pii;
typedef pair<ll,pii> piii;
 
#define ff first
#define ss second
#define eb emplace_back
#define ep emplace
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(), (x).end()
#define compress(v) sort(all(v)), v.erase(unique(all(v)), v.end())
#define IDX(v, x) lower_bound(all(v), x) - v.begin()
//cout<<fixed;
//cout.precision(12);
 
struct poi{
    ll val,xx,yy;
};
 
vector<ll> x;
ll n,m;
ll mod=998244353;
string s;
pii arr[1010101];
ll dp[1010101];
 
bool sf(pii a,pii b){
    return a.ff+a.ss<b.ff+b.ss;
}
priority_queue<ll,vector<ll>,greater<ll>> pq;
int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    ll t,T;
    cin>>T;
    dp[0]=1;
    for(t=1;t<=T;t++){
        ll i,j,k,l;
        ll ans=0;
        cin>>n;
        for(i=1;i<=210100;i++)
            dp[i]=0;
 
        for(i=1;i<=n;i++)
            cin>>arr[i].ff>>arr[i].ss;
        sort(arr+1,arr+1+n,sf);
        for(i=1;i<=n;i++){
            for(j=arr[i].ff;j>=0;j--){
                if(dp[j]){
                    //cout<<i<<' '<<j<<' '<<j+arr[i].ss<<'\n';
                    ans=max(j+arr[i].ss,ans);
                    dp[j+arr[i].ss]++;
                }
            }
        }
 
        cout<<"Case #"<<t<<": "<<ans<<'\n';
    }
}
cs

'코딩 > 백준 문제 풀이' 카테고리의 다른 글

BOJ 7117 - Sevens, twos and zeros  (0) 2022.08.20
BOJ 8311 - Variable Subsequences  (0) 2022.08.19
BOJ 17670 - 난  (0) 2022.08.14
BOJ 5542 - JOI 국가의 행사  (0) 2022.08.13
BOJ 25351 - 중간 구간 게임  (0) 2022.07.11