第二行,输入k个正整数,表示k枚导弹的高度,按来袭导弹的袭击时间顺序给出,以空格分隔。
8
300 207 155 300 299 170 158 65
6
分析:很明显该题的核心问题的是求得一个最大高度,使其满足可以拦截最多的导弹。因为拦截系统每次的拦截高度是递减的,那么这就是最长不增子序列。依然可以运用下面的推导公式:
F[1] = 1;
F[i] = max{1,F[j] + 1|j<i && a[j]>=a[i]};
代码实现:
#include <iostream> using namespace std; const int MAXSIZE = 25; const int MIN = 0; int arr[MAXSIZE]; int F[MAXSIZE]; int main() { int k; int maxLen; while (cin >> k) { memset(F, 0, MAXSIZE); F[0] = 1; for (int i = 0; i < k; i++) { cin >> arr[i]; F[i] = 1; } for (int i = 1; i < k; i++) { maxLen = MIN; for (int j = 0; j < i; j++) { if (arr[i] <= arr[j] && maxLen < F[j]) { maxLen = F[j]; } } F[i] = maxLen + 1; } maxLen = F[0]; for (int t = 1; t < k; t++) if (F[t] > maxLen ) maxLen = F[t]; cout << maxLen << endl; } }
扩展一下,如果需要打印拦截的所有导弹的高度。那么可以增加一个路径数组,用来记录每次选择的中间点。easy,代码如下:
#include <iostream> using namespace std; const int MAXSIZE = 25; const int MIN = 0; int arr[MAXSIZE]; int F[MAXSIZE]; int path[MAXSIZE];//存储路径 int main() { int k; int maxLen; int index; while (cin >> k) { memset(F, 0, MAXSIZE); F[0] = 1; for (int i = 0; i < k; i++) { cin >> arr[i]; F[i] = 1; path[i] = i; } for (int i = 1; i < k; i++) { maxLen = MIN; for (int j = 0; j < i; j++) { if (arr[i] <= arr[j] && maxLen < F[j]) { maxLen = F[j]; index = j; } } F[i] = maxLen + 1; path[i] = index; } maxLen = F[0]; for (int t = 1; t < k; t++) if (F[t] > maxLen) { maxLen = F[t]; index = t; } cout << maxLen << endl; while (F[index] != 1) { cout << arr[index] << ‘ ‘; index = path[index]; } cout << arr[index] << endl; } }
原文:http://www.cnblogs.com/tgycoder/p/5034219.html