题目大意
N个士兵排成一排,不是按照高度顺序排列。现在想要从中去掉几名士兵,从而使得队伍中剩余的士兵能够看到这排最左边或者最右边的那个士兵,某士兵能够看到最左边(或最右边)的士兵指这名士兵和最左边(或最右边)士兵之间没有另外一名士兵的高度大于等于这名士兵。
题目分析
典型的最长xx子序列问题,能够满足要求的队列有四种:
(1)严格上升子序列
(2)严格下降子序列
(3)以某个士兵为中心,左边上升,右边下降子序列
(4)以士兵i左边为上升子序列,士兵j右边为下降子序列,且i在j左边。
然后排成上述四种队形,找满足某个队形要求的最大的队列中人数。
实现(c++)
#include<stdio.h> #include<iostream> #include<string> #include<string.h> #include<vector> #include<stack> #include<queue> #include<deque> #include<list> #include<set> #include<set> #include<map> #include<functional> #include<algorithm> using namespace std; typedef long long ll; double height[1005]; int dp_inc[1005]; //从最左边到达i处,以i结尾的最长上升子序列长度 int dp_dec[1005]; //从i到达最右边,以i开头的最长下降子序列长度 int Solve(int n){ for (int i = 0; i < n; i++){ dp_inc[i] = 1; for (int j = i - 1; j >= 0; j--){ if (height[j] < height[i]){ dp_inc[i] = max(dp_inc[i], dp_inc[j] + 1); } } } for (int i = n - 1; i >= 0; i--){ dp_dec[i] = 1; for (int j = i + 1; j < n; j++){ if (height[j] < height[i]){ dp_dec[i] = max(dp_dec[i], dp_dec[j] + 1); } } } int result = 0; for (int i = 0; i < n; i++){ //选择左侧上升,右侧下降 for (int j = i; j < n; j++){ result = max(result, dp_inc[i] + dp_dec[j] - (i == j));//如果i和j重合,则去掉重合的一次 } } return result; } int main(){ int n; scanf("%d", &n); for (int i = 0; i < n; i++){ scanf("%lf", &height[i]); } int result = Solve(n); printf("%d ", n - result); return 0; }