BOJ 3343 - 장미

image.png

aa 집의 개수 NaN_a와 가격 CaC_a, bb집의 개수 NbN_b와 가격 CbC_b 라 하자.

aa 집의 꽃을 사는 묶음 수를 uu , bb 집의 꽃을 사는 묶음 수를 vv라 하자.

NNau+NbvN \le N_a \cdot u+N_b \cdot v 그리고 총 가격은

C=Cau+Cbv C=C_a \cdot u+C_b \cdot v

위 부등식을 vv에 대해 나타내면

NNauNbv \dfrac {N-N_a \cdot u}{N_b} \le v

이므로 uu가 정해지면 vvvNNauNb=NNau+Nb1Nbv \ge \left\lceil \dfrac {N-N_a \cdot u}{N_b} \right\rceil=\left\lfloor \dfrac {N-N_a \cdot u+N_b-1}{N_b} \right\rfloor 여야 한다.

이제 aa가 항상 더 가성비가 안좋다고 해보자.

LCM(Na,Nb)LCM(N_a,N_b) 를 봤을 때, 이 만큼의 그룹은 항상 더 가성비가 좋은 bb로 사는게 이득이다.

그럼 aa를 최대 Nb1N_b-1개 까지 사는것만 확인하고 나머지는 bb로 채워주는것이 항상 최적이다.

aaNbN_b개 사버리면 그건 그냥 bbNaN_a 개 사는게 더 이득이라 항상 손해기 때문이다.

Nb105N_b \le 10^5이므로 브루트포스로 이 문제를 해결할 수 있다.

void solve() {  
   int n;  
   // <개수, 가격>  
   pi a, b;  
   cin >> n >> a.fi >> a.se >> b.fi >> b.se;  
  
   auto get_v = [&](int u) {  
      return max(0ll, (n - a.fi * u + b.fi - 1) / b.fi);  
   };  
   auto get_cost = [&](int u) {  
      int v = get_v(u);  
      return u * a.se + v * b.se;  
   };  
  
   int ans = 2e18;  
   for (int u = 0; u <= min((n + a.fi - 1) / a.fi, 999999ll); u++) ans = min(ans, get_cost(u));  
   swap(a, b);  
   for (int u = 0; u <= min((n + a.fi - 1) / a.fi, 999999ll); u++) ans = min(ans, get_cost(u));  
   cout << ans;  
}

Tags:

Categories:

Updated:

Comments