关于最后求完两个dp数组后如何找最大值的两种AC方法讨论
查看原帖
关于最后求完两个dp数组后如何找最大值的两种AC方法讨论
266440
PetterZhukov楼主2020/9/3 12:07

我把两个dp数组求出来了,根据题解,之后是取1~n为中间那个i,如何开始遍历最大

根据这个思想,我写了第一份ac代码

#include <stdio.h>
#include <stdlib.h>
int num[105],flag[105],flag2[105];
int MAX(int l,int r,int *num)	//这段程序没有用上
{
    int max=l;
    for(int i=l+1;i<=r;i++)
    {
        if(num[i]>num[max]) max=i;
    }
    return max;
}

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&num[i]);
        flag[i]=flag2[i]=1;
    }
    for(int i=2;i<=n;i++) //dp1
    {
        for(int k=1;k<i;k++)
            if(num[i]>num[k] && flag[k]+1>flag[i])
                flag[i]=flag[k]+1;
    }
    for(int i=n-1;i>=1;i--) //dp2
    {
        for(int k=n;k>i;k--)
            if(num[i]>num[k] && flag2[k]+1>flag2[i])
                flag2[i]=flag2[k]+1;
    }
    int max=0;
    for(int i=0;i<=n;i++)	//max
    {
        if(flag[i]+flag2[i]-1>max)  max=flag[i]+flag2[i]-1;
    }
    printf("%d\n",n-max);
    return 0;
}

但是我觉得最后关于max的讨论不对,不应该是在0~i和i~n两段分别取最长升子序列和最长降子序列吗,那个“最长”并没有在程序中体现出来啊

于是我把最后部分改成了

for(int i=0;i<=n;i++)
    {
        if(flag[MAX(1,i,flag)]+flag2[MAX(i,n,flag2)]-1>max)
            max=flag[MAX(1,i,flag)]+flag2[MAX(i,n,flag2)]-1;
    }

将最后部分替换,代码变成了这样(前面不变)

#include <stdio.h>
#include <stdlib.h>
int num[105],flag[105],flag2[105];
int MAX(int l,int r,int *num)
{
    int max=l;
    for(int i=l+1;i<=r;i++)
    {
        if(num[i]>num[max]) max=i;
    }
    return max;
}

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&num[i]);
        flag[i]=flag2[i]=1;
    }
    for(int i=2;i<=n;i++)  //dp1
    {
        for(int k=1;k<i;k++)
            if(num[i]>num[k] && flag[k]+1>flag[i])
                flag[i]=flag[k]+1;
    }
    for(int i=n-1;i>=1;i--)  //dp2
    {
        for(int k=n;k>i;k--)
            if(num[i]>num[k] && flag2[k]+1>flag2[i])
                flag2[i]=flag2[k]+1;
    }
    int max=0;
    for(int i=0;i<=n;i++)	//max
    {
        if(flag[MAX(1,i,flag)]+flag2[MAX(i,n,flag2)]-1>max)
            max=flag[MAX(1,i,flag)]+flag2[MAX(i,n,flag2)]-1;
    }
    printf("%d\n",n-max);
    return 0;
}

同样AC了

第二种我很好理解,但是第一种为什么会AC呢?

我觉得应该会存在i对应的dp1数组和dp2数组不是最大值的情况,那就不能简答地将flag[i],flag2[i]相加了。

是数据弱的原因吗,还是这两种方法实际上是等效的

2020/9/3 12:07
加载中...