poj 1836 Alignment(线性dp)

题目链接:http://poj.org/problem?id=1836

思路分析:假设数组为A[0, 1, …, n],求在数组中最少去掉几个数字,构成的新数组B[0, 1, …, m]满足条件B[0] < B[1] <….<B[i] 且 B[i+1] > … > B[m];

该问题实质为求A[0, …, k]的最长递增子序列和A[j, …, n]中的最长递减子序列(0 <= k <= n, 0 <= j <= n, k < j);所以求出A[0, .., k]的最长递增子序列

与A[j, …, n]中的最长递减子序列,在枚举k与j的值,求出最大的和,在用人数减去最大和即可;

 

代码如下:

#include <iostream>
using namespace std;

const int MAX_N = 1000 + 10;
double num[MAX_N];
int dp_l[MAX_N], dp_r[MAX_N];

inline int Max(int a, int b) { return a - b > 0 ? a : b; }
int main()
{
    int n;

    while (scanf("%d", &n) != EOF)
    {
        for (int i = 0; i < n; ++ i)
            scanf("%lf", &num[i]);

        for (int i = 0; i < n; ++ i)
        {
            dp_l[i] = 1;
            for (int j = 0; j < i; ++ j)
            {
                if (num[j] < num[i])
                    dp_l[i] = Max(dp_l[i], dp_l[j] + 1);
            }
        }
        for (int i = n - 1; i >= 0; -- i)
        {
            dp_r[i] = 1;
            for (int j = n - 1; j > i; -- j)
            {
                if (num[j] < num[i])
                    dp_r[i] = Max(dp_r[i], dp_r[j] + 1);
            }
        }

        int ans = 0;
        for (int i = 0; i < n; ++ i)
        {
            int temp = dp_l[i];
            for (int j = i + 1; j < n; ++ j)
            {
                if (temp + dp_r[j] > ans)
                    ans = temp + dp_r[j];
            }
        }
        ans = Max(ans, dp_l[n - 1]);
        ans = Max(ans, dp_r[0]);
        
        printf("%d\n", n - ans);
    }
    return 0;
}
posted @ 2015-05-23 20:50  Leptus  阅读(186)  评论(0编辑  收藏  举报