洛谷 P1020 导弹拦截 最长上升子序列 dp 思路

题目描述

某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。

输入导弹依次飞来的高度(雷达给出的高度数据是\le 50000≤50000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

输入格式
11行,若干个整数(个数\le 100000≤100000)

输出格式
22行,每行一个整数,第一个数字表示这套系统最多能拦截多少导弹,第二个数字表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

思路

第一问求最多能拦截的导弹数目很简单(其实是n^2)
第二问求至少要布置几套导弹就有点懵逼了QWQ

首先想到用数组来维护每套导弹拦截下来的导弹。
比如m1储存第一套导弹拦截下来的最低的导弹,
如果m1存不下就往m2里存,
如果有多套导弹就贪心的放,
然后有几个m就是最少几套导弹。

然后。。。。。。。。
我发现数组m是最长上升子序列。
?????????????
我也不知道为啥??????

389 207 155 300 299 170 158 65

用样例模拟的话
m1: 389 207 155
m2: 300 399 170 158 65
刚好是结果2

然后就这么做出来了???

代码

#include
using namespace std;

int a[1000010], f1[1000010], f2[1000010];
int n=1, max1, max2;

int max(int a, int b) {
	if (a > b)
		return a;
	return b;
}

int main() {
	while (scanf("%d", &a[n]) == 1)
		n++;
	n--;
	
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j < i; j++) {
			if (a[j] >= a[i]) 
				f1[i] = max(f1[j], f1[i]);
			if (a[j] < a[i]) 
				f2[i] = max(f2[j], f2[i]);
		}
		f1[i]++;
		f2[i]++;
		max1 = max(max1, f1[i]);
		max2 = max(max2, f2[i]);
	}
	printf("%d\n%d", max1, max2);
	return 0;
}

你可能感兴趣的:(洛谷 P1020 导弹拦截 最长上升子序列 dp 思路)