导弹拦截 && 最长不下降子序列

T1最长不下降子序列

样例:
in :13 7 9 16 38 24 37 18 44 19 21 22 63 15
out: 8
(还有需要输出的子序列)

局部解析

找子序列的方法,这个理论上来说是可以用队列的方法的,但是由于需要输出最后的序列,队列的方法没法用,所以用n2的方法。

for(int i = 1; i <= n; i++) {
    dp[i] = 1;
    for(int j = 1; j <= i; j++) {
	    if(a[i] > a[j]) {
		    if(dp[i] < dp[j] + 1) {
			    dp[i] = dp[j] + 1;
			    path[i] = j;
		    }
	    }
    }
}

首先是找到子序列,基本逻辑就是只能从前面比他小的接过来,找到最优的。然后用path记录路径。

for(int i = 1; i <= n; i++) {
    if(dp[i] > tot) {
	    tot = dp[i];
	    biao = i;
    }
}

扫一遍找到最大值
接下来是精华:
那么我们已经用path存了路径,我们该怎么输出路径呢?
链前思想,从后往前。

int fucking = biao;
for(int i = 1; i  <= tot; i++) {
    finally[i] = a[fucking];
    fucking = path[fucking];
}
for(int i = tot; i >= 1; i--) {
    printf("%d " ,finally[i]);
}

完整代码

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n;
int a[100001];
int finally[1000001];
int path[1000001];
int dp[1000001];
int biao;
int tot = 0;
int main() {
    while(scanf("%d" ,&a[++n]) != EOF);
    n--;
    for(int i = 1; i <= n; i++) {
	    dp[i] = 1;
	    for(int j = 1; j <= i; j++) {
		    if(a[i] > a[j]) {
		    if(dp[i] < dp[j] + 1) {
				    dp[i] = dp[j] + 1;
				    path[i] = j;
			    }
		    }
	    }
    }
    for(int i = 1; i <= n; i++) {
	    if(dp[i] > tot) {
		    tot = dp[i];
		    biao = i;
	    }
    }
    printf("max=%d\n" ,tot);
    int fucking = biao;
    for(int i = 1; i  <= tot; i++) {
	    finally[i] = a[fucking];
	    fucking = path[fucking];
    }
    for(int i = tot; i >= 1; i--) {
	    printf("%d " ,finally[i]);
    }
    return 0;
}

T2导弹拦截

题目描述

某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出的高度数据是≤50000 \le 50000≤50000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

解析

不难发现,这道题分为两个过程:首先求出最长不上升子序列得到最多拦截多少个导弹,然后是零件分组的类似方法(贪心的思想,对于每一组能被拦截的导弹,如果新来的导弹比这里面最大的还大,就新开一组,否则就找第一个比他大的那一组的最大值进行更新),得到最后的最少安多少套系统。

代码

#include<cstdio>
#include<algorithm>
using namespace std;
int n;
int a[1000001];
int tot = 0;
int ans[10000001];
int l[1000001] = { };
bool cmp(int x,int y) {
    return x > y;
}
int main() {
    while(scanf("%d" ,&a[++n]) != EOF);
    n--;
    tot++;
    ans[tot] = a[tot];
    for(int i = 2; i <= n; i++) {
	    if(a[i] <= ans[tot]) {
		    tot++;
		    ans[tot] = a[i];
	    }
	    if(a[i] > ans[tot]) {
		    int q = upper_bound(ans + 1,ans + 1 + tot,a[i],cmp) - ans;
		    ans[q] = a[i];
	    }
    }
    printf("%d\n" ,tot);
    int biao = 1;
    l[1] = a[1];
    for(int i = 2; i <= n; i++) {
	    if(a[i] > l[biao]) {
		    biao++;
		    l[biao] = a[i];
	    }
	    if(a[i] <= l[biao]) {
		    int q = lower_bound(l + 1,l + 1 + biao,a[i]) - l;
		    l[q] = a[i];
	    }
    }
    printf("%d\n" ,biao);
    return 0;
}
posted @ 2021-04-17 17:33  24Kmagic  阅读(59)  评论(0)    收藏  举报