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;
}
posted @ 2012-04-29 15:57  E_star  阅读(210)  评论(0编辑  收藏  举报