[USACO17JAN] Subsequence Reversal P

根据数据范围,不难想到 DP 状态应该是 n4 级别的。

先考虑当没有反转区间的操作时如何转移。

dpl,r,L,R 表示当前区间为 lr,值域 [L,R] 时的答案。转移时枚举四个维度,可以从 dpl,r,L,R1,dpl,r,L+1,R,dpl+1,r,L,R,dpl,r1,L,R 转移过来。

加上翻转操作后,我们思考其本质。翻转一个子序列可以理解为交换某几对数字的位置,这样的话相当于如果 al=R 或者 ar=L 的话,我们可以通过翻转 lr 中的任意一个包含 l,r 的子序列来满足条件,即 dpl,r,L,R=dpl+1,r1,L,R+[al=R]+[ar=L]

由于区间 DP 按照区间从小到大的顺序,故可以保证这样的翻转满足题目条件,所以这道题就结束了。

#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int read()
{
	int w=1,s=0;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch)){s=s*10+(ch-'0');ch=getchar();}
	return w*s;
}
const int mod=998244353;
const int maxn=51;
const int inf=3e17+7;
int n,a[maxn],dp[maxn][maxn][maxn][maxn];
signed main()
{
#ifdef Lydic
	freopen(".in", "r", stdin);
	freopen(".out", "w", stdout);

//  #else
//   	freopen("Stone.in","r",stdin);
//   	freopen("Stone.out","w",stdout);
#endif
    cin>>n;
    for(int i=1;i<=n;i++)a[i]=read();
    for(int i=1;i<=n;i++)
        for(int l=1;l<=a[i];l++)
            for(int r=a[i];r<=50;r++)
                dp[i][i][l][r]=1;
    for(int len=2;len<=n;len++)
    {
        for(int l=1;l<=n-len+1;l++)
        {
            int r=l+len-1;
            for(int lenn=1;lenn<=50;lenn++)
            {
                for(int L=1;L<=50-lenn+1;L++)
                {
                    int R=L+lenn-1;
                    dp[l][r][L][R]=max(dp[l][r][L+1][R],dp[l][r][L][R-1]);
                    dp[l][r][L][R]=max(dp[l][r][L][R],dp[l+1][r][L][R]+(a[l]==L));
                    dp[l][r][L][R]=max(dp[l][r][L][R],dp[l][r-1][L][R]+(a[r]==R));
                    dp[l][r][L][R]=max(dp[l][r][L][R],dp[l+1][r-1][L][R]+(a[l]==R)+(a[r]==L));
                }
            }
        }
    }
    cout<<dp[1][n][1][50];
	return 0;
}

posted @   Redamancy_Lydic  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示