习题:A Twisty Movement (DP)

题目

传送门

思路

注意题目中的最后一段话

这意味这选出的序列可以不是连续的

之后我们考虑最后的答案长什么样子

因为只能反转一次

所以最后的答案一定是由4个部分组成

[1111\(\cdots\)] [222\(\cdots\)] [111\(\cdots\) ] [222\(\cdots\) ]

如果没有可以看成空序列

之后就直接暴力DP搞就行了

\(dp_{i,j}\)表示前\(i\)个数,前\(j\)个部分的最大值

\(\begin{cases}dp_{i,1}=dp_{i-1,1}+(a_i==1)\\dp_{i,2}=max(dp_{i,1},dp_{i-1,2}+(a_i==2)\\dp_{i,3}=max(dp_{i,2},dp_{i-1,3}+(a_i==1)\\dp_{i,4}=max(dp_{i,3},dp_{i-1,4}+(a_i==2)\end{cases}\)

很明显第一维是可以省略的

然而空间本来就够,所以省不省都无所谓了

代码

#include<iostream>
using namespace std;
int n;
int a[2005];
int dp[2005][5];
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    for(int i=1;i<=n;i++)
    {
        dp[i][1]=dp[i-1][1]+(a[i]==1);
        dp[i][2]=max(dp[i][1],dp[i-1][2]+(a[i]==2));
        dp[i][3]=max(dp[i][2],dp[i-1][3]+(a[i]==1));
        dp[i][4]=max(dp[i][3],dp[i-1][4]+(a[i]==2));
    }
    cout<<dp[n][4];
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/loney-s/p/12275932.html