문제를 읽어보면,, 완탐으로 한다고 하면 지금 상태를 3개 봐야한다.
=> 3개의 상태값 맞물려야함.
1) 현재 시간,
2) 자두가 몇번 이동,
3) (문제에서 직접 언급은 없지만, ) 1번 나무, 2번 나무 선택
-> 일반적인 완탐으로 하기에는 전혀 부적절하다 생각함.

=> 확실한 거는 상태값을 매겨서 자두를 얻을 수 있는 최대값을 구해야 한다. 생각했고, 3개의 상태값을 이용한 탑다운으로 진행하기로 결정함.
문제에서 t만큼의 나무 번호가 주어짐.
=> 비교 대상이다.

1) 코드에서 0으로 반환해야 함.
-> go 함수 내에서 비교 인덱스가 v[t] 와 비교하는 상황을 만들면 , out of range이기 때문이다.
if(ttime == t) return 0;




1 ^ 1 => 0 , 0 ^ 1 => 1

여기는 비교하는 여기서 out of Range 처리하기 위한 등호이고, 비교 대상이 완전히 끝났으므로 0 반환이다.

여기가 중요하다.
문제를 읽어보면, 입력값 w만큼만 이동을 해야 하는데, w를 초과하게 되면, 이를 0으로 반환해야 하는 것인가?
지문을 보면, 반드시 cnt만큼만 이동해야 한다고 했는데, 우리는 2개의 함수, 1)가만히 있기, 2)움직이기 코드가 있는 상황이고,
2)번 움직이는 코드에 대한 처리가 필요하다!
그래서 초과되는 cnt 움직였다고 하면 잘못된 상황이므로 가장 큰값을 반환하고 있는 것이다.

#include <iostream>
#include <vector>
#include <memory.h>
#include <algorithm>
#include <string>
using namespace std;
#include <string>
#include <vector>
int t, w;
vector<int> v;
int memo[1001][31][2];
// 3가지 상태를 맞물리면서 풀어야함.
int go(int ttime, int mov, int num)
{
if (mov > w)
return -1e9;
if (ttime == t)
return 0;
int& ret = memo[ttime][mov][num];
if (ret != -1)
return ret;
// 1일때 0으로
// 0일때 1로 변경해야 함.
int eat = (num == v[ttime] ? 1 : 0);
// 그대로
ret = eat + max(go(ttime + 1, mov, num),
go(ttime + 1, mov + 1, 1 - num));
return ret;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
// 변경되는 상태값이 2개뿐이고,
// 왼쪽 오른쪽으로 움직인다.
// 맨 처음에는 1에 있다.
// 매 순간 1 에 있을수도, 2에 있을 수도
// 를 진행하면서 최대로 자두나무를 받는 카운트는?
cin >> t >> w;
v.resize(t);
for (int i = 0; i < t; ++i)
{
cin >> v[i];
v[i] -= 1;
}
memset(memo, -1, sizeof(memo));
cout << max(go(0, 0, 0), go(0,1,1));
return 0;
}