pku 1836 Alignment DP (LIS)

http://poj.org/problem?id=1836

其实前不久校赛的题目就是这个题目的一个简化版本,http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2403 这道题只要求出从左到右,从右到左,以及Ak1<Ak2<Ak3<...<Amid-1<Amid>Amid+1>...>Akm-2>Akm-1>Akm (k1,k2,k3....km均在1到n之间) 严格按照左边递增右边递减的序列长度去最大就好了。

这里的题意和SDUT2403差不多,只是对于第三个条件放松吧了,中间可以出现相等的。这样中间相等的那两个可能挨着也可能不挨着所以要循环遍历一次。

View Code
#include <iostream>

#include <cstring>

#include <cstdio>

#define maxn 1007

using namespace std;





int dpl[maxn],dpr[maxn];

double a[maxn];

int n;



void LIS(int flag,int *dp)

{

    int i,j;

    if (flag == 0)

    {

        dp[0] = 1;

        for (i = 1; i < n; ++i)

        {

            int m = 0;

            for (j = 0; j < i; ++j)

            {

                if (a[i] > a[j]) m = max(m,dp[j]);

            }

            dp[i] = m + 1;

        }

    }

    else

    {

        dp[n - 1] = 1;

        for (i = n - 2; i >= 0; --i)

        {

            int m = 0;

            for (j = n - 1; j > i; --j)

            {

                if (a[i] > a[j]) m = max(m,dp[j]);

            }

            dp[i] = m + 1;

        }



    }

}

int main()

{

   //freopen("in.txt","r",stdin);

    int i,j;

    while (~scanf("%d",&n))

    {

        for (i = 0; i < n; ++i) scanf("%lf",&a[i]);

        LIS(0,dpl);//从左到右记录最长上升子序列

        LIS(1,dpr);//从右到左记录最长上升子序列

        int ans = 0;

        //对于中间的那点不存在相等的情况

        for (i = 0; i < n; ++i)

        ans = max(ans,dpl[i] + dpr[i] - 1);

        //对于中间的一点存在相等的情况,且不挨着

        for (i = 0; i < n; ++i)

        {

            for (j = i +  1; j < n; ++j)

            {

                ans = max(ans,dpl[i] + dpr[j]);

            }

        }

        printf("%d\n",n - ans);

    }

    return 0;

}

你可能感兴趣的:(pku)