码迷,mamicode.com
首页 > 其他好文 > 详细

poj_1836 动态规划

时间:2015-09-26 15:59:03      阅读:115      评论:0      收藏:0      [点我收藏+]

标签:

题目大意

    N个士兵排成一排,不是按照高度顺序排列。现在想要从中去掉几名士兵,从而使得队伍中剩余的士兵能够看到这排最左边或者最右边的那个士兵,某士兵能够看到最左边(或最右边)的士兵指这名士兵和最左边(或最右边)士兵之间没有另外一名士兵的高度大于等于这名士兵。

题目分析

    典型的最长xx子序列问题,能够满足要求的队列有四种: 
(1)严格上升子序列 
(2)严格下降子序列 
(3)以某个士兵为中心,左边上升,右边下降子序列 
(4)以士兵i左边为上升子序列,士兵j右边为下降子序列,且i在j左边。 
通过动态规划,求出 
(1)dp_inc_beg[i]从i到到队尾的最长上升序列长度; 
(2)dp_inc_end[i]从队头到i的最长上升序列长度; 
(3)dp_dec_beg[i]从i到队尾的最长下降子序列长度; 
(4)dp_dec_end[i]从队头到i的最长下降子序列长度 
然后排成上述四种队形,找满足某个队形要求的最大的队列中人数。

实现(c++)

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int dp_inc_beg[1005];	//dp_inc_beg[i]表示从i到到队尾的最长上升序列长度
int dp_inc_end[1005];	//dp_inc_end[i]表示从队头到i的最长上升序列长度
int dp_dec_beg[1005];
int dp_dec_end[1005];

double height[1005];
int main(){
	int n;
	scanf("%d", &n);

	for (int i = 1; i <= n; i++){
		scanf("%lf", &height[i]);
	}
	memset(dp_inc_beg, 0, sizeof(dp_inc_beg));
	memset(dp_inc_end, 0, sizeof(dp_inc_end));
	memset(dp_dec_beg, 0, sizeof(dp_dec_beg));
	memset(dp_dec_end, 0, sizeof(dp_dec_end));


	for (int i = 1; i <= n; i++){
		int max_inc = 0, max_dec = 0;
		for (int j = 1; j < i; j++){
			if (height[i] > height[j])
				max_inc = max_inc > dp_inc_end[j] ? max_inc : dp_inc_end[j];
			if (height[i] < height[j])
				max_dec = max_dec > dp_dec_end[j] ? max_dec : dp_dec_end[j];
		}
		dp_inc_end[i] = max_inc + 1;
		dp_dec_end[i] = max_dec + 1;
	}
	for (int i = n; i >= 1; i--){
		int max_inc = 0, max_dec = 0;
		for (int j = i + 1; j <= n; j++){
			if (height[i] < height[j])
				max_inc = max_inc > dp_inc_beg[j] ? max_inc : dp_inc_beg[j];
			if (height[i] > height[j])
				max_dec = max_dec > dp_dec_beg[j] ? max_dec : dp_dec_beg[j];
		}
		dp_inc_beg[i] = max_inc + 1;
		dp_dec_beg[i] = max_dec + 1;
	}
	int max = 0;
	for (int i = 1; i <= n; i++){
		//最大上升序列长度
		if (dp_inc_beg[i] + dp_inc_end[i] - 1 > max){
			max = dp_inc_beg[i] + dp_inc_end[i] - 1;
		}
		//最大下降序列长度
		if (dp_dec_beg[i] + dp_dec_end[i] - 1 > max){
			max = dp_dec_beg[i] + dp_dec_end[i] - 1;
		}
		//如果以i为中心,向两边均呈下降序列
		if (dp_inc_end[i] + dp_dec_beg[i] - 1 > max){
			max = dp_inc_end[i] + dp_dec_beg[i] - 1;
		}
		//左边一个上升序列[1...i] 右边一个下降序列[j...n], 其中 i < j
		for (int j = i + 1; j <= n; j++){
			if (dp_inc_end[i] + dp_dec_beg[j] > max)
				max = dp_dec_beg[j] + dp_inc_end[i];
		}
	}
	printf("%d\n", n - max);
	return 0;
}

 

poj_1836 动态规划

标签:

原文地址:http://www.cnblogs.com/gtarcoder/p/4840846.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!