Notice
Recent Posts
Recent Comments
Link
«   2026/06   »
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
Archives
Today
Total
관리 메뉴

dh-winternagi 님의 블로그

(33918) 맛있는 스콘 만들기 본문

백준 (C++)/Solve

(33918) 맛있는 스콘 만들기

dh-winternagi 2026. 4. 21. 23:13

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

단계별로 풀어보기

38단계(스택, 큐, 덱 2) 9번째

 

 

 

여기까지 왔을 정도면 PS 경험치가 충분히 쌓였을테니 제한을 보고 추측할 수 있다.

덱 최대값 테크닉은 보통 O(N)이었는데, 여기서 N이나 M의 범위가 그것보다 작다. 따라서 O(NM)이라고 눈치껏 알아낼 수 있다.

문제가 어려워지면 어떤 알고리즘을 써야 할지부터 막막해지기 때문에 이렇게 제한 범위를 보며 가능한 해답의 시간 복잡도를 추측하는 것은 실제로 도움이 된다.

 

dp[k][x]를 시각 k-1에 온도를 x로 맞췄을 때 맛의 최대값이라고 하자.

이때 dp[k][x]= f(k,x)+max(dp[k-1][y])이다. f(k,x)는 문제에서 설명한 대로 M-|b(k-1)-x|이고 max(dp[k-1][y])는 덱 최대값 테크닉으로 구하면 된다.

이 과정을 시각 0부터 N-1까지, 온도 1부터 M까지 순회하며 DP를 갱신하면 된다.

단 주의할 점이 두 가지가 있다.

온도를 C의 정수배만큼 조절할 수 있으므로, 온도를 순회할 때 1,1+C,1+2C, ... ,(초기화)2,2+C,2+2C, ... ,(초기화)3, ... 이런 식으로 순회해야 한다.

또 x를 갱신하기 위해 탐색해야 하는 y의 가능한 범위는 x-d부터 x+d까지이므로 이를 고려해 갱신 시기를 잘 설정해야 한다.

 

이 문제도 dp[k]라인을 갱신할 때 dp[k-1]라인만 있으면 되므로 메모리를 줄일 수 있다.

 

 

 

#include <iostream>
#include <vector>
#include <deque>
#include <algorithm>
using namespace std;

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);
  
  int n, m, c, d;
  
  cin >> n >> m >> c >> d;
  
  vector<int> v(n);
  vector dp(2, vector<int> (m+1));
  deque<int> dq;
  
  for(int i=0;i<n;i++)  cin >> v[i];
  
  for(int i=1;i<=m;i++)  dp[0][i]= m-abs(v[0]-i);
  
  for(int i=1;i<n;i++){
    for(int j=1;j<c+1;j++){
      dq.clear();
      
      for(int t=j;t<=m+d;t+=c){
        while(!dq.empty() && t<=m && dp[0][dq.back()]<dp[0][t])  dq.pop_back();
        
        if(t<=m)  dq.push_back(t);
        
        while(dq.front()<t-2*d)  dq.pop_front();
        
        if(1<=t-d)  dp[1][t-d]= dp[0][dq.front()]+m-abs(v[i]-(t-d));
      }
    }
    
    dp[0]= dp[1];
  }
  
  cout << *max_element(dp[0].begin()+1, dp[0].end());
  
  return 0;
}

'백준 (C++) > Solve' 카테고리의 다른 글

(11758) CCW  (0) 2026.04.21
(2166) 다각형의 면적  (0) 2026.04.21
(15678) 연세워터파크  (0) 2026.04.21
(5977) Mowing the Lawn  (0) 2026.04.21
(11003) 최솟값 찾기  (0) 2026.04.21