题解 | #合唱队形#

合唱队形

http://www.nowcoder.com/practice/0045cd3e39634a66ada63c2adeb49234

思路

关于怎么理解“峰型”队形:
以160,170,155,180,170,160为例。
对于其中的每个人,我们求两个值,分别设dp1[6] 与dp2[6]
其中dp1[i] 意为从0开始 到i为止 这前几个人的最长上升子序列长度。如,对于180的人而言,dp1[3] = 3 (也就是 160,170,180) 同理。dp2[i] 意为从i开始 到末尾为止 这后几个人的最长下降子序列长度。如,对于180的人而言,dp2[3] = 3 (也就是 180,170,160)

两个量求和,再减1(因为他自己被算了两次),得到的是“峰型”序列的长度。对180而言,该数是3+3-1=5

所有位置的峰型序列长度 最大的就是整个队伍能形成的最大峰型队列长度

则需要至少6-5 = 1 个出列

#include<iostream>
#include<cstring>
/*
合唱队形
*/
using namespace std;
const int MAXN = 1000+1;
int arr[MAXN];
int dp1[MAXN];
int dp2[MAXN];

void getUp(int n){
	//得到各个位置 以其为结尾的最大上升子序列
	for (int i = 0; i < n; ++i){
		dp1[i] = 1;
		for (int j = 0; j < i; ++j){
			if(arr[i] > arr[j]){
				dp1[i] = max(dp1[i],dp1[j] + 1);
			}
		}
	}
}

void getDown(int n){
	//得到各个位置 以其为结尾的最大上升子序列
	for (int i = n - 1; i >= 0; --i){
		dp2[i] = 1;
		for (int j = n - 1; j > i; --j){
			if(arr[i] > arr[j]){
				dp2[i] = max(dp2[i],dp2[j] + 1);
			}
		}
	}
}

int main(){
	int n;
	cin>>n;
	for (int i = 0; i < n; ++i){
		cin>>arr[i];
	}
	memset(dp1,0,sizeof(dp1));
	getUp(n);
	//得到各个位置 以其为结尾的最大上升子序列
	memset(dp2,0,sizeof(dp2));
	getDown(n);
	//得到各个位置 以其为结尾的最大上升子序列
	int maxUpDown = 1;
	//记录先上升后下降的最长序列长度
	for (int i = 0; i < n; ++i){
		maxUpDown = max(maxUpDown,dp1[i] + dp2[i] -  1);
	}
	//求剔除人数
	int res = n - maxUpDown;
	cout<<res<<endl;

	return 0;
}

全部评论

相关推荐

11-27 17:08
已编辑
牛客_产品运营部_私域运营
腾讯 普通offer 24k~26k * 15,年包在36w~39w左右。
点赞 评论 收藏
分享
我在朝九晚六双休的联想等你:如果我是你,身体素质好我会去参军,然后走士兵计划考研211只需要200多分。
点赞 评论 收藏
分享
评论
6
1
分享
牛客网
牛客企业服务