P1091 [NOIP2004 提高组] 合唱队形

题面

\(n\) 位同学站成一排,音乐老师要请其中的 \(n-k\) 位同学出列,使得剩下的 \(k\) 位同学排成合唱队形。

合唱队形是指这样的一种队形:设 \(k\) 位同学从左到右依次编号为 \(1,2,\)\(,k\),他们的身高分别为 \(t_1,t_2,\)\(,t_k\),则他们的身高满足 \(t_1< \cdots <t_i>t_{i+1}>\)\(>t_k(1\le i\le k)\)

你的任务是,已知所有 \(n\) 位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。

思路

其实思路很简单,就是跑两遍最长上升子序列,然后再枚举中间的求最大值。

最长上升子序列问题

本题 \(O(n^2)\) 算法可过。

方程如下:

\[f[i]=\max_{j<i \text{ and } a_j < a_i} \{ f[j] \} + 1 \]

代码

#include <bits/stdc++.h>
using namespace std;

int n, a[105], f[3][105], ans = INT_MIN;

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++)cin >> a[i];
	for (int i = 1; i <= n; i++) {
		for (int j = 0; j < i; j++) {
			if (a[i] > a[j]) {
				f[0][i] = max(f[0][i], f[0][j] + 1);
			}
		}
	}
	for (int i = n; i >= 1; i--) {
		for (int j = n + 1; j > i; j--) {
			if (a[i] > a[j]) {
				f[1][i] = max(f[1][i], f[1][j] + 1);
			}
		}
	}
	for (int i = 1; i <= n; i++) {
		ans = max(f[0][i] + f[1][i]-1, ans);
	}
	ans=n-ans;
	cout << ans << endl;
	return 0;
}
posted @ 2022-02-19 16:32  蒟蒻xiezheyuan  阅读(53)  评论(0编辑  收藏  举报