1 条题解

  • 0
    @ 2025-8-24 21:53:21

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar zyj_Orz
    为了伯伦希尔的荣耀,为了休伯利安的名义!!!

    搬运于2025-08-24 21:53:21,当前版本为作者最后更新于2019-01-28 08:44:57,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    排版已订正。

    DP题。

    感觉蓝题难度还是有点过了吧?

    大致思路就是建一个二维数组dp【i】【j】表示从第i个人到第j个人对称的最小次数

    这时候就大致可以得出动态转移方程了,如下


    1.先设置一个长度l自2至n枚举


    2.此时i从1枚举至n-l+1,j此时则为i+l-1。


    3.当第i个人颜色等于第j个人时,dp【i】【j】则与dp【i+1】【j-1】相同,赋值;


    4.如果不同的话,则为{dp【i+1】【j】,dp【i】【j-1】,dp【i+1】【j-1】}中次数最少的那一个再+1了。


    故状态转移方程代码如下:

    if(a[i]==a[j]) dp[i][j]=dp[i+1][j-1];//相同情况
            else dp[i][j]=min(dp[i+1][j],min(dp[i][j-1],dp[i+1][j-1]))+1;
    

    最后输出dp【1】【n】则为正解。


    发现了吗?实际上代码很精简的。只要你有心,省选难度在你眼里都将是水题!

    PS:初始化会WA第七个点!

    #include<bits/stdc++.h>
    using namespace std;
    int n,a[3001],dp[3001][3001];//dp[i][j]表示i到j对称的最小次数 
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int l=2;l<=n;l++)
        for(int i=1;i+l<=n+1;i++)//枚举第i个人
        {
            int j=i+l-1;//枚举第j个人
            if(a[i]==a[j]) dp[i][j]=dp[i+1][j-1];
            else dp[i][j]=min(dp[i+1][j],min(dp[i][j-1],dp[i+1][j-1]))+1;
        }
        cout<<dp[1][n];
    }
    

    PPS:这是@M_sea dalao給我们讲解的,深入浅出Orz

    PPPS:应该没有题解与这个相似吧?因为我们全机房都是听的M_sea dalao讲解的,所以可能机房会有与我相似的题解投上来QAQ

    • 1

    信息

    ID
    2784
    时间
    1000ms
    内存
    125MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者