poj_1836 动态规划

题目大意

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;
}
时间: 2024-10-30 05:46:34

poj_1836 动态规划的相关文章

Leetcode 494 Target Sum 动态规划 背包+滚动数据

这是一道水题,作为没有货的水货楼主如是说. 题意:已知一个数组nums {a1,a2,a3,.....,an}(其中0<ai <=1000(1<=k<=n, n<=20))和一个数S c1a1c2a2c3a3......cnan = S, 其中ci(1<=i<=n)可以在加号和减号之中任选. 求有多少种{c1,c2,c3,...,cn}的排列能使上述等式成立. 例如: 输入:nums is [1, 1, 1, 1, 1], S is 3. 输出 : 5符合要求5种

活动选择的贪心算法与动态规划(未完成)

// greedy_algorithm.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> #include<queue> using namespace std; #define NofActivity 11 int c[NofActivity + 1][NofActivity + 1]; int reme[NofActivity + 1][NofActivity + 1]; //活动的

求不相邻金币相加和的最大值--动态规划1

求不相邻金币相加和的最大值. 输入n个金币的金币面值(正数自定义),求这些金币不相邻和的最大值. 动态规划问题1 设f(n)为第n个金币数的最大值,f(0)=0,f(1)=a[1],输入的数组从下标为1开始. f(n)=max{a[n]+f(n-2),f(n-1)}. 代码如下: import java.util.Scanner; public class Jin_bi_zui_da_zhi { public static void main(String[] args) { Scanner s

[动态规划] 黑客的攻击 Hacker&#39;s CrackDown Uva 11825

抽象为数学模型就是,  取尽可能多的互不相交的子集 ,  使得每一个子集都能覆盖全集 #include <algorithm> #include <cstring> #include <cstdio> using namespace std; int n; int P[1000],cover[1000],f[1000]; int main(){ scanf("%d", &n); for (int i = 0; i < n;i++) {

Beauty Of algorithms(七)动态规划 钢条分割 矩阵链乘 最长公共子序列 最优二叉树

1.动态规划                动态规划的方法与方法类似,英文"dynamic programming",这里的programming不是程序的意思,而是一种表格法.都是通过组合子问题的解来解决原问题,分治方法将划分为互不相交的子问题,递归的求解子问题,再将它们的解组合起来求出原问题的解.与之相反动态规划应用于子问题的重叠情况,即不同的子问题具有公共的子问题,子问题的求解是递归进行 的,将其划分为更小的子问题,动态规划,每个子问题只求解一次,将其保存在表格中,从而无需每次求

Hdoj 1176 免费馅饼 【动态规划】

免费馅饼 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 26110    Accepted Submission(s): 8905 Problem Description 都说天上不会掉馅饼,但有一天gameboy正走在回家的小径上,忽然天上掉下大把大把的馅饼.说来gameboy的人品实在是太好了,这馅饼别处都不掉,就掉落在他身旁的1

Fibonacci斐波拉契数列----------动态规划DP

n==10 20 30 40 50 46 体验一下,感受一下,运行时间 #include <stdio.h>int fib(int n){ if (n<=1)     return 1; else            return fib(n-1)+fib(n-2); }int main( ){ int n; scanf("%d",&n); printf("%d\n" ,fib(n) );} 先 n==10 20 30 40 50 46

pat 1068 动态规划/Fina More Conis

1068. Find More Coins (30) Eva loves to collect coins from all over the universe, including some other planets like Mars. One day she visited a universal shopping mall which could accept all kinds of coins as payments. However, there was a special re

动态规划(4)——最长上升子序列(作业题NYOJ201)

作业题 描述 小白同学这学期有一门课程叫做<数值计算方法>,这是一门有效使用数字计算机求数学问题近似解的方法与过程,以及由相关理论构成的学科-- 今天他们的Teacher S,给他们出了一道作业题.Teacher S给了他们很多的点,让他们利用拉格朗日插值公式,计算出某严格单调函数的曲线.现在小白抄下了这些点,但是问题出现了,由于我们的小白同学上课时走了一下神,他多抄下来很多点,也就是说这些点整体连线不一定还是严格递增或递减的了.这可怎么处理呢.为此我们的小白同学制定了以下的取点规则: 1.取