문제링크 : https://www.acmicpc.net/problem/22857
22857번: 가장 긴 짝수 연속한 부분 수열 (small)
수열 $S$에서 최대 $K$번 원소를 삭제한 수열에서 짝수로 이루어져 있는 연속한 부분 수열 중 가장 긴 길이를 출력한다.
www.acmicpc.net
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int MAX = 987654321;
int N, K, arr[50001];
int dp[50001][101];
int func(int cur, int cnt)
{
if(cur > N-1 || cnt > K) return 0; //범위 및 삭제 횟수 체크
int result = 0;
if(dp[cur][cnt]) return dp[cur][cnt];
if(arr[cur]%2) result = max(result, func(cur+1, cnt+1)); //홀수 (삭제)
else result = max(result, func(cur+1, cnt)+1); //짝수 (삭제 x)
dp[cur][cnt] = result; //값 저장
return dp[cur][cnt];
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cin >> N >> K;
for(int i=0; i<N; i++) cin >> arr[i];
int result = 0;
for(int i=0; i<N; i++) result = max(result, func(i, 0)); //현재 위치 기준 K번 삭제 시작
cout << result;
return 0;
}
수열의 각 위치 별로 K번 삭제를 실시하여 가장 큰 값을 찾아준다.
삭제의 경우 홀수일 떄만 하면되기에 현재 위치의 값이 짝수인지 홀수인지 체크가 필요하다.
먼저 홀수인 경우는 삭제 과정이 이뤄진다.
삭제를 카운팅하기 위해 재귀로 다음 값을 이어서 탐색할 때, cnt를 1 증가시켜 K 번 횟수를 넘는지 아닌지 체크한다.
마찬가지로 위치가 이동했기에 cur를 1 증가시켜 위치를 이동시키고 해당 위치가 N-1을 넘어서는지도 체크가 필요하다.
만약 짝수이면 삭제 과정이 불필요하다.
따라서 재귀로 다음 값을 이어서 탐색할 때 삭제 횟수를 체크하는 cnt는 증가시킬 필요가 없다.
그리고 짝수의 경우 수열의 길이가 증가하므로 재귀로 탐색한 값 + 1을 해주어야 한다.
이후 재귀를 통해 누적된 최종 dp 값을 반환해준다.
모든 위치에 대해 이 행위를 반복하기에 반복할 떄마다 최대값을 따로 저장해주고 저장한 최대값을 출력해주어야 한다.
'백준 > 실버' 카테고리의 다른 글
[백준 6236번] 용돈 관리 (C++) (0) | 2024.02.28 |
---|---|
[백준 1072번] 게임 (C++) (0) | 2024.02.26 |
[백준 17216번] 가장 큰 감소 부분 수열 (C++) (0) | 2024.02.22 |
[백준 25214번] 크림 파스타 (C++) (0) | 2024.02.21 |
[백준 12101번] 1, 2, 3 더하기 2 (C++) (0) | 2024.02.20 |