• poj_1836 动态规划


    题目大意

        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;
    }
    
  • 相关阅读:
    (二十九)动态单元格
    (二十八)QQ好友列表的展开收缩
    (二十七)QQ好友列表的实现
    (二十六)静态单元格(Cell)
    (二十五)键盘的设置与TextField细节处理
    poj 1734 Sightseeing trip
    BZOJ 2200: [Usaco2011 Jan]道路和航线
    LUOGU P1073 最优贸易
    poj 3662 Telephone Lines
    poj 3539 Elevator
  • 原文地址:https://www.cnblogs.com/gtarcoder/p/4840846.html
Copyright © 2020-2023  润新知