北京大学机试 合唱队形 需要二刷 *最长非连续子序列衍生问题

基本思想:

思想已经领悟,但是卡在了一个最后的寻找方法上,卡了1个用例;

 

最后寻找的应该是中间节点,而不是遍历,找后续的最长序列。否则会遇到这种问题:

1 2 3 3 2 1;

使用找中间节点则是3是中间节点,总和为5,序列为1,2,3,2,1;

而如果用自己最初的思想,则是总和为6,序列为1,2,3,3,2,1;

原因在于当i=3的时候,后面3,2,1会使得dp[i+1]最大为3,多计算一次,因为题目中给出的要求不能相等;

 

关键点:

无;

 

#include<iostream>
#include<stdlib.h>
#include<vector>
#include<algorithm>
using namespace std;

const int maxn = 110;
int n;
int d[maxn];
int dp1[maxn];
int dp2[maxn];

void preorder() {
	dp1[0] = 1;
	for (int i = 1; i < n; i++) {
		dp1[i] = 1;
		for (int j = 0; j < i; j++) {
			if (d[i] > d[j]&& dp1[j]+1> dp1[i]) {
				dp1[i] = dp1[j] + 1;
			}
		}
	}
}
void postorder() {
	reverse(d, d + n);
	dp2[0] = 1;
	for (int i = 1; i < n; i++) {
		dp2[i] = 1;
		for (int j = 0; j < i; j++) {
			if (d[i] > d[j] && dp2[j] + 1 > dp2[i]) {
				dp2[i] = dp2[j] + 1;
			}
		}
	}
	reverse(dp2, dp2 + n);
	reverse(d, d + maxn);
}

int cnt = 0;

int main() {
	while (cin >> n) {
		for (int i = 0; i < n; i++) {
			cin >> d[i];
		}
		preorder();
		postorder();
		for (int i = 0; i < n - 1; i++) {
			int ans = dp1[i]+dp2[i]-1;
			if (cnt < ans)
				cnt = ans;
		}
		cout << n-cnt << endl;
	}
	return 0;
}

  

posted @ 2020-04-01 20:25  暮云林凌  阅读(194)  评论(0)    收藏  举报