풀이

[백준] 9569 - No Change (c++)

땅왕 2025. 1. 20. 23:35

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

 

문제 요약

사야 하는 물건 N개와 들고 있는 동전 K개의 가치가 주어진다. 꼭 순서대로 사야하며 여러개를 한 번에 살 수 있다. 또한 거스름돈을 받을 수 없다. 이 때 남기는 돈의 최대값을 구해라.

 

풀이 (2^KlogN)

  • 비트dp
  • 누적합
  • 이분탐색

dp[k];  dp[i]=동전 비트마스크가 i일 때 살 수 있는 물건의 최대 개수로 정의 해준다. 물건 가격의 누적합 배열을 만들어 두면 이분탐색으로 logN에 업데이트를 해줄 수 있다. upper_bound(all(psum),psum[이미 먹은 개수]+쓸 동전 가치) 이렇게

#include <bits/stdc++.h>
using namespace std;
#define ll long long

int main() {
    cin.tie(0)->sync_with_stdio(0);
    
    int k,n;cin>>k>>n;
    int c[k],p[n],ps[n+1]{},sum=0;
    for(int& x:c) cin >>x,sum+=x;
    int i=1;
    for(int& x:p) cin>> x,ps[i++]=ps[i-1]+x;

    array<int,2> dp[1<<k]{};
    int ans =-1;
    for(int i=1;i<1<<k;i++) {
        for(int j=0;j<k;j++) if(i&1<<j){
            auto pre=dp[i^1<<j];
            dp[i][0]=max(dp[i][0],int(upper_bound(ps+1,ps+n+1,ps[pre[0]]+c[j])-ps)-1);
            dp[i][1]=pre[1]+c[j];
            if(dp[i][0]==n) ans=max(ans,sum-dp[i][1]);
        }
    }   
    cout<<ans;
}