ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준 15961] 회전 초밥
    C 프로그래밍/BOJ 2022. 8. 29. 20:40
    728x90

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

     

    15961번: 회전 초밥

    첫 번째 줄에는 회전 초밥 벨트에 놓인 접시의 수 N, 초밥의 가짓수 d, 연속해서 먹는 접시의 수 k, 쿠폰 번호 c가 각각 하나의 빈 칸을 사이에 두고 주어진다. 단, 2 ≤ N ≤ 3,000,000, 2 ≤ d ≤ 3,000, 2

    www.acmicpc.net

    #include <cstdio>
    int N, d, k, c;	// 접시수, 가짓수, 연속, 쿠폰번호
    int lookup[3000 + 2];
    int plate[3000000 + 2];
    
    void input()
    {
    	scanf("%d %d %d %d", &N, &d, &k, &c);
    	for (int i = 0; i < N; i++) {
    		scanf("%d", &plate[i]);
    	}
    }
    
    
    int get_max()
    {
    	int max = 0;	// 최대가짓수
    	int cnt = 1;	// 현재 먹은 가짓수	// 쿠폰의 초밥은 무조건 먹는다. 
    	lookup[c] = 1;	
    
    	// 초기 룩업테이블 생성 
    	for (int i = 0; i < k; i++) {
    		lookup[plate[i]] += 1;
    		if (lookup[plate[i]] == 1) cnt++;	// 종류 한 개가 방금 추가됨
    	}
    
    	for (int i = 1; i < N; i++) {
    		lookup[plate[(i + k - 1) % N]] += 1;
    		if (lookup[plate[(i + k - 1) % N]] == 1) cnt++;
    
    		lookup[plate[i - 1]] -= 1;
    		if (lookup[plate[i - 1]] == 0) cnt--;
    
    		max = (max < cnt) ? cnt : max;
    	}
    	return max;
    }
    
    
    
    int main()
    {
    	input();
    	int ans = get_max();
    	printf("%d\n", ans);
    	return 0;
    }

    이 문제는 [백준 2531] 회전초밥 문제와 동일하게 풀면 타임아웃이 발생한다. 

    이유는 인풋 배열 크기가 100배 차이 나기 때문이다.

    실버 문제에서는 diff 배열에서 0이 아닌 원소를 체크하며 cnt를 세어줬다면, 이 문제에서는 "슬라이딩 윈도우"를 통해 해결해야 한다. 

     

     

    // get_max() 함수

    쿠폰의 초밥은 항상 먹을 수 있으므로 cnt = 1, loolup[c] = 1로 초기화한다. 

     

    첫 번째 루프에서는 처음 k개를 돌면서, 초기 슬라이딩 윈도우를 만들어 준다. 

    초밥을 먹고 난 후 룩업 테이블의 값이 0에서 1로 바뀌었다면, 새로운 종류의 초밥을 먹은 것이므로 cnt를 증가시킨다. 

     

    두 번째 루프는 슬라이딩 윈도우를 한 칸씩 이동하며 탐색하는 용도이다. 

    이미 첫번째 루프에서 인덱스  i = 0에 대하여 연속해서 k개의 초밥을 먹었을 경우를 탐색해주었기 때문에, 인덱스 i = 1부터 탐색을 진행한다. 

    만약 (i + k -1) % N 번째 초밥을 먹고 난 후, 룩업테이블의 값이 0에서 1로 바뀌었다면, 새로운 종류의 초밥을 먹은 것이므로 cnt를 증가시킨다. 

    한편 슬라이딩 윈도우의 크기를 항상 k로 유지해주기 위해 i - 1번째 먹었던 초밥은 삭제해준다. 제거 후 룩업테이블의 값이 1에서 0으로 바뀌었다면, 한 종류의 초밥이 삭제된 것이므로 cnt를 감소시킨다. 

     

    매 탐색 후 max 값과 cnt 값을 비교하여 먹을 수 있는 가짓수의 최대값을 갱신해준다. 

    728x90

    'C 프로그래밍 > BOJ' 카테고리의 다른 글

    [정올 1328] 빌딩  (0) 2022.08.31
    [정올 1141] 불쾌한 날(Bad Hair Day)  (0) 2022.08.31
    [백준 15686] 치킨 배달  (0) 2022.08.28
    [백준 10026] 적록색약  (0) 2022.08.27
    [백준 2583] 영역 구하기  (0) 2022.08.27

    댓글

Designed by Tistory.