πŸ•οΈ ICPC Sinchon/Two Pointer

[BOJ S1][C++] λ°±μ€€ 2531번: νšŒμ „ 초λ°₯

선달 2022. 10. 20. 03:22
λ°˜μ‘ν˜•

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

 

2531번: νšŒμ „ 초λ°₯

첫 번째 μ€„μ—λŠ” νšŒμ „ 초λ°₯ λ²¨νŠΈμ— 놓인 μ ‘μ‹œμ˜ 수 N, 초λ°₯의 κ°€μ§“μˆ˜ d, μ—°μ†ν•΄μ„œ λ¨ΉλŠ” μ ‘μ‹œμ˜ 수 k, 쿠폰 번호 cκ°€ 각각 ν•˜λ‚˜μ˜ 빈 칸을 사이에 두고 주어진닀. 단, 2 ≤ N ≤ 30,000, 2 ≤ d ≤ 3,000, 2 ≤

www.acmicpc.net

 

문제

νšŒμ „ 초λ°₯ μŒμ‹μ μ—λŠ” νšŒμ „ν•˜λŠ” 벨트 μœ„μ— μ—¬λŸ¬ 가지 μ’…λ₯˜μ˜ 초λ°₯이 μ ‘μ‹œμ— 담겨 놓여 있고, μ†λ‹˜μ€ 이 μ€‘μ—μ„œ μžκΈ°κ°€ μ’‹μ•„ν•˜λŠ” 초λ°₯을 κ³¨λΌμ„œ λ¨ΉλŠ”λ‹€. 초λ°₯의 μ’…λ₯˜λ₯Ό 번호둜 ν‘œν˜„ν•  λ•Œ, λ‹€μŒ 그림은 νšŒμ „ 초λ°₯ μŒμ‹μ μ˜ 벨트 μƒνƒœμ˜ 예λ₯Ό 보여주고 μžˆλ‹€. 벨트 μœ„μ—λŠ” 같은 μ’…λ₯˜μ˜ 초λ°₯이 λ‘˜ 이상 μžˆμ„ 수 μžˆλ‹€. 

μƒˆλ‘œ 문을 μ—° νšŒμ „ 초λ°₯ μŒμ‹μ μ΄ 뢈경기둜 μ˜μ—…μ΄ μ–΄λ €μ›Œμ„œ, λ‹€μŒκ³Ό 같이 두 가지 행사λ₯Ό ν†΅ν•΄μ„œ 맀상을 올리고자 ν•œλ‹€.

  1. μ›λž˜ νšŒμ „ 초λ°₯은 μ†λ‹˜μ΄ λ§ˆμŒλŒ€λ‘œ 초λ°₯을  κ³ λ₯΄κ³ , 먹은 초λ°₯만큼 μ‹λŒ€λ₯Ό κ³„μ‚°ν•˜μ§€λ§Œ, 벨트의 μž„μ˜μ˜ ν•œ μœ„μΉ˜λΆ€ν„° k개의 μ ‘μ‹œλ₯Ό μ—°μ†ν•΄μ„œ 먹을 경우 ν• μΈλœ μ •μ•‘ κ°€κ²©μœΌλ‘œ μ œκ³΅ν•œλ‹€. 
  2. 각 κ³ κ°μ—κ²Œ 초λ°₯의 μ’…λ₯˜ ν•˜λ‚˜κ°€ 쓰인 쿠폰을 λ°œν–‰ν•˜κ³ , 1번 행사에 μ°Έκ°€ν•  경우 이 쿠폰에 μ ν˜€μ§„ μ’…λ₯˜μ˜ 초λ°₯ ν•˜λ‚˜λ₯Ό μΆ”κ°€λ‘œ 무료둜 μ œκ³΅ν•œλ‹€. λ§Œμ•½ 이 λ²ˆν˜Έμ— μ ν˜€μ§„ 초λ°₯이 ν˜„μž¬ 벨트 μœ„μ— 없을 경우, μš”λ¦¬μ‚¬κ°€ μƒˆλ‘œ λ§Œλ“€μ–΄ μ†λ‹˜μ—κ²Œ μ œκ³΅ν•œλ‹€.  

μœ„ 할인 행사에 μ°Έμ—¬ν•˜μ—¬ κ°€λŠ₯ν•œ ν•œ λ‹€μ–‘ν•œ μ’…λ₯˜μ˜ 초λ°₯을 먹으렀고 ν•œλ‹€. μœ„ 그림의 예λ₯Ό 가지고 μƒκ°ν•΄λ³΄μž. k=4이고, 30번 초λ°₯을 쿠폰으둜 λ°›μ•˜λ‹€κ³  κ°€μ •ν•˜μž. 쿠폰을 κ³ λ €ν•˜μ§€ μ•ŠμœΌλ©΄ 4가지 λ‹€λ₯Έ 초λ°₯을 먹을 수 μžˆλŠ” κ²½μš°λŠ” (9, 7, 30, 2), (30, 2, 7, 9), (2, 7, 9, 25) μ„Έ 가지 κ²½μš°κ°€ μžˆλŠ”λ°, 30번 초λ°₯을 μΆ”κ°€λ‘œ 쿠폰으둜 먹을 수 μžˆμœΌλ―€λ‘œ (2, 7, 9, 25)λ₯Ό κ³ λ₯΄λ©΄ 5가지 μ’…λ₯˜μ˜ 초λ°₯을 먹을 수 μžˆλ‹€. 

νšŒμ „ 초λ°₯ μŒμ‹μ μ˜ 벨트 μƒνƒœ, 메뉴에 μžˆλŠ” 초λ°₯의 κ°€μ§“μˆ˜, μ—°μ†ν•΄μ„œ λ¨ΉλŠ” μ ‘μ‹œμ˜ 개수, 쿠폰 λ²ˆν˜Έκ°€ μ£Όμ–΄μ‘Œμ„ λ•Œ, μ†λ‹˜μ΄ 먹을 수 μžˆλŠ” 초λ°₯ κ°€μ§“μˆ˜μ˜ μ΅œλŒ“κ°’μ„ κ΅¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€. 

μž…λ ₯

첫 번째 μ€„μ—λŠ” νšŒμ „ 초λ°₯ λ²¨νŠΈμ— 놓인 μ ‘μ‹œμ˜ 수 N, 초λ°₯의 κ°€μ§“μˆ˜ d, μ—°μ†ν•΄μ„œ λ¨ΉλŠ” μ ‘μ‹œμ˜ 수 k, 쿠폰 번호 cκ°€ 각각 ν•˜λ‚˜μ˜ 빈 칸을 사이에 두고 주어진닀. 단, 2 ≤ N ≤ 30,000, 2 ≤ d ≤ 3,000, 2 ≤ k ≤ 3,000 (k ≤ N), 1 ≤ c ≤ d이닀. 두 번째 쀄뢀터 N개의 μ€„μ—λŠ” 벨트의 ν•œ μœ„μΉ˜λΆ€ν„° μ‹œμž‘ν•˜μ—¬ νšŒμ „ λ°©ν–₯을 λ”°λΌκ°ˆ λ•Œ 초λ°₯의 μ’…λ₯˜λ₯Ό λ‚˜νƒ€λ‚΄λŠ” 1 이상 d μ΄ν•˜μ˜ μ •μˆ˜κ°€ 각 μ€„λ§ˆλ‹€ ν•˜λ‚˜μ”© 주어진닀. 

좜λ ₯

주어진 νšŒμ „ 초λ°₯ λ²¨νŠΈμ—μ„œ 먹을 수 μžˆλŠ” 초λ°₯의 κ°€μ§“μˆ˜μ˜ μ΅œλŒ“κ°’μ„ ν•˜λ‚˜μ˜ μ •μˆ˜λ‘œ 좜λ ₯ν•œλ‹€.

 

풀이

크기가 k인 μŠ¬λΌμ΄λ”© μœˆλ„μš°λ₯Ό μ‚¬μš©ν•œλ‹€

// Authored by : seondal
// Co-authored by : -

// #include <bits/stdc++.h>
#include <iostream>
#include <vector>
#include <deque>

using namespace std;

// 인자둜 받은 eat 큐 λ‚΄μ˜ 초λ°₯의 μ’…λ₯˜μ˜ 갯수λ₯Ό μΉ΄μš΄νŠΈν•΄μ„œ 리턴
int countKind(deque<int> q, int k, int d, int c) {
    vector<bool> isEat(d+1, false);
    isEat[c] = true;
    
    for(int i=0; i<k; i++) {
        isEat[q.front()]=true;
        q.pop_front();
    }
    
    int kind = 0;
    for(int i=1; i<=d; i++) {
        if(isEat[i])
            kind++;
    }
    
    return kind;
}

// 먹을 수 μžˆλŠ” 초λ°₯의 μ΅œλŒ€ κ°€μ§“μˆ˜
int maxKind(int n, int d, int k, int c, vector<int>&sushi) {
    deque<int> eat;
    for(int i=0; i<k; i++)
        eat.push_back(sushi[i]);
    
    int max_kind = countKind(eat, k, d, c);
        
    for(int i=k; i<n+k; i++) {
        int end = i>=n ? i-n : i;  // μŠ¬λΌμ΄λ”© μœˆλ„μš°μ— μΆ”κ°€ν•  인덱슀 (sushi 벑터λ₯Ό νšŒμ „ν•΄μ•Όν•˜λ―€λ‘œ μ˜ˆμ™Έμ²˜λ¦¬)

        eat.pop_front();
        eat.push_back(sushi[end]);

        max_kind = max(max_kind, countKind(eat, k, d, c));
    }
    
    return max_kind;
}

int main() {
    ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    
    int n, d, k, c;
    cin >> n >> d >> k >> c;
    vector<int> sushi(n);
    for(int i=0; i<n; i++)
        cin >> sushi[i];

    cout << maxKind(n, d, k, c, sushi);
    
    return 0;
}

/*
 */
λ°˜μ‘ν˜•