题解 | #拦截导弹#
拦截导弹
https://www.nowcoder.com/practice/218f3db1f66d465bbf9578625aa90785
根据 Dilworth 定理(一个有序集合的最小链划分数等于最大反链的大小),我们可以知道:
- 最小链划分数:把导弹高度序列划分成若干条递减序列所需的最小数量。
- 最大反链的大小:一个最长上升子序列的长度(因为两个元素不可比较的意思就是:它们可以构成一个递增的关系)
可以将序列化分为若干个递减子序列 =》 通过找到最长上升子序列的数量来求解
#include <algorithm> #include <cstring> #include <functional> #include <iostream> #include <vector> using namespace std; const int N = 1010; int a[N]; int f[N]; int maxLength(int n) { int res = 0; for (int i = 0; i < n; i ++) { f[i] = 1; for (int j = 0; j < i; j ++) { if (a[i] <= a[j]) f[i] = max(f[j] + 1, f[i]); } res = max(res, f[i]); } return res; } int minSystem(int n) { int res = 0; for (int i = 0; i < n; i ++) { f[i] = 1; for (int j = 0; j < i; j ++) { //Dilworth if (a[i] > a[j]) { f[i] = max(f[i], f[j] + 1); } } res = max(f[i], res); } return res; } int main() { int n; cin >> n; for (int i = 0; i < n; i ++) cin >> a[i]; cout << maxLength(n) << endl; memset(f, 0, sizeof f); cout << minSystem(n) << endl; return 0; }