当前位置: 首页 > 工具软件 > twisty > 使用案例 >

A. A Twisty Movement dp

谷梁翰飞
2023-12-01

https://codeforces.com/problemset/problem/933/A

 

这个是一个dp,但是我并没有看出来,然后也不太会写,

这种题一般应该要想到先预处理前缀和后缀,然后再进行dp

dp[i][j][0]----表示从区间 i~j 以2结尾的最长递减序列 

dp[i][j][1]----表示从区间 i~j 以1结尾的最长递减序列

为什么这样定义,我很迷,完全不知道要这么写,?

dp[i][j][0]=dp[i][j-1][0]+(a[i]==2)

dp[i][j][1]=max(dp[i][j-1][0],dp[i][j-1][1]+(a[i]==1))

这个状态转移方程还是很好想的,如果是以2结尾的最长递减序列,那么状态转移就只有一种

如果是以1结尾的最长递减序列,可以是前面为2最后为1,也可以是一直是1。

 

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<vector>
#define inf 0x3f3f3f3f
#define debug(x) cout<<"-----"<<" x = "<<x<<"-----"<<endl
using namespace std;
typedef long long ll;
const int maxn = 2e3 + 10;
ll dp[maxn][maxn][3];
int a[maxn];
ll pre[maxn], suf[maxn];
int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    for (int i = 1; i <= n; i++)  pre[i] = pre[i - 1] + (a[i]==1);
    for (int i = n; i >= 1; i--)  suf[i] = suf[i + 1] + (a[i]==2);
    ll ans = 0;
    for(int i=1;i<=n;i++)
    {
        for(int j=i;j<=n;j++)
        {
            dp[i][j][0] = dp[i][j - 1][0] + (a[j] == 2);//代表以2结尾的最长的递减序列
            dp[i][j][1] = max(dp[i][j - 1][0], dp[i][j - 1][1]) + (a[j] == 1);//代表以1结尾的最长的递减序列

            ans = max(ans, pre[i - 1] + dp[i][j][0] + suf[j + 1]);
            ans = max(ans, pre[i - 1] + dp[i][j][1] + suf[j + 1]);
        }
    }
    printf("%lld\n", ans);
    return 0;
}

 

转载于:https://www.cnblogs.com/EchoZQN/p/10908105.html

 类似资料:

相关阅读

相关文章

相关问答