풀이
[백준] 29200 - 문제 수 줄이기 (c++)
땅왕
2024. 8. 28. 18:44
https://www.acmicpc.net/problem/29200
문제 요약
N크기의 수열이 주어진다. 수열을 구간으로 분할하는데 인접한 수열끼리 크기가 같으면 안 된다. 수열끼리 xor한 값의 합이 최대가 되도록 분할하고 합을 출력해라.
풀이 (N)
- DP
- 애드혹
일단 xor은 각 비트 자리에 1이 단 하나만 있어야 비트가 켜지기 때문에 잘게 쪼갤 수록 이득이란 걸 알 수 있다. 언뜻 보고 1,2,3 크기로만 분할해서 최댓값을 만들 수 있을 줄 알았지만
6 1 1 2 4 8 8 |
이런 반례 케이스가 있었다(3까지 포함하면 22, 4까지 포함하면 24 나옴). 4까지 포함하니 최댓값을 만들 수 있었다.
제한시간이 넉넉해서 한 1~10까지 써도 상관은 없다. 제한적인 숫자로 최댓값을 구성할 수 있다는 걸 직감을 통해 알아내야 하는 애드혹 문제였다.
dp[i][j]를 i까지 나눴고 가장 마지막에 j크기로 나눴을 때 최댓값으로 정의하면 쉽게 답을 구할 수 있다.
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int main() {
cin.tie(0)->sync_with_stdio(0);
int n;cin >>n;
int a[n+1];
for(int i=1;i<=n;i++)
cin>>a[i];
vector<array<ll,5>> dp(n+1);
for(int i=1;i<=n;i++) {
dp[i].fill(-1e18);
int x =a[i];
for(int j=1;j<=min(i,4);j++) {
for(int k=1;k<=4;k++)
if(k!=j)
dp[i][j] =max(dp[i][j],dp[i-j][k]+x);
x^=a[i-j];
}
}
cout <<*max_element(dp[n].begin(),dp[n].end());
}