题目链接: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 - ans); } return 0; }