본문 바로가기

Coding Test

백준 15961 회전 초밥

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

#include <iostream>
#include <vector>


using namespace std;

int sushi[3001];

int main() {

    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    int n, d, k, c;
    int ans = 0;

    cin >> n >> d >> k >> c;

    vector<int> arr(n);

    for (int i = 0; i < n; i++) {
        cin >> arr[i];
    }

    int s = 0;
    int e = k - 1;



    int cnt = 0;

    for (int i = s; i <= e; i++) {
        if(!sushi[arr[i]]) {
            cnt++;
        }
        sushi[arr[i]]++;
    }

    if (!sushi[c]) {
        ans = cnt + 1;
    } else {
        ans = cnt;
    }

    do {

        if (--sushi[arr[s]] == 0) {
            cnt--;
        }
        s = (s + 1) % n;
        e = (e + 1) % n;
        if (sushi[arr[e]]++ == 0) {
            cnt++;
        }

        if (!sushi[c]) {
            ans = max(ans, cnt + 1);
        } else {
            ans = max(ans, cnt);
        }


    } while (s != 0);


    cout << ans;

    return 0;
}

 슬라이딩 윈도우 문제이다.

 윈도우 안에 연속으로 먹는 초밥의 종류를 저장하고, 하나씩 이동시켜가면서 초밥의 종류의 수를 갱신시키며 풀 수 있다.

 

 윈도우 초기화

    int s = 0;
    int e = k - 1;


    int cnt = 0;

    for (int i = s; i <= e; i++) {
        if(!sushi[arr[i]]) {
            cnt++;
        }
        sushi[arr[i]]++;
    }

    if (!sushi[c]) {
        ans = cnt + 1;
    } else {
        ans = cnt;
    }

 

 k 개의 초밥을 연속으로 먹어야 하므로 입력받은 초밥의 처음부터 k 개의 초밥을 센다. sushi는 현재 윈도우에 있는 초밥의 개수를 뜻하고, 이 값이 0이면 새로운 종류의 초밥을 먹는다는 뜻이므로 cnt에 반영한다. 

 연산이 끝나고, 쿠폰으로 주어지는 초밥을 먹지 않았다면 종류를 더하고, 아니면 그대로 반영한다.

 윈도우 이동

    do {

        if (--sushi[arr[s]] == 0) {
            cnt--;
        }
        s = (s + 1) % n;
        e = (e + 1) % n;
        if (sushi[arr[e]]++ == 0) {
            cnt++;
        }

        if (!sushi[c]) {
            ans = max(ans, cnt + 1);
        } else {
            ans = max(ans, cnt);
        }


    } while (s != 0);

 

 포인터 s가 한 바퀴 돌아 제자리로 돌아갈 때 까지 윈도우를 한 칸씩 이동한다. 앞의 초밥이 빠졌을 때 해당 종류가 없어진다면 cnt--, 뒤의 초밥이 더해졌을 때 초밥의 종류가 추가된다면 cnt++ 하여 종류를 반영한다. 이후, 행사에 참여하여 준 쿠폰에 적힌 초밥을 먹지 않았다면 cnt+1하여 반영하고, 먹었다면 그대로 반영한다.

 

 이렇게 하여 ans에 저장된 값을 출력하여 답을 구할 수 있다.

'Coding Test' 카테고리의 다른 글

백준 2473 세 용액  (0) 2024.05.24
백준 16926 배열 돌리기 1  (0) 2024.05.23
백준 17073 나무 위의 빗물  (1) 2024.05.21
백준 1766 문제집  (0) 2024.05.20
백준 17609 회문  (1) 2024.05.19