北京大学机试 合唱队形 需要二刷 *最长非连续子序列衍生问题
基本思想:
思想已经领悟,但是卡在了一个最后的寻找方法上,卡了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;
}

浙公网安备 33010602011771号