dp--P1020导弹拦截

题目描述

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

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

输入格式

11行,若干个整数(个数\le 100000100000)

输出格式

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

 1  for(int i=1; i<=n; i++) {
 2         f[i]=1;
 3         for(int j=t; j>0; j--)
 4             if(a[i]<=a[dp[j]]) {
 5                 f[i]=f[dp[j]]+1;
 6                 break;
 7             }
 8         t=max(t,f[i]);
 9         dp[f[i]]=i;
10         ans=max(ans,f[i]);
11     }

i 1 2 3 4 5 6 7 8

a 389 207 155 300 299 170 158 65

f 1 2 3 2 3 4 5 6

发现当f的值相同时,越后面的导弹高度越高

用dp[i]维护f值为i的最后一个导弹的位置,t记录当前已经求出最长不升子序列长度

递推求f时枚举a[dp[t]],a[dp[t-1]],。。。,a[dp[1]]是否≥当前求的导弹高度,是就更新f

 1 #include<algorithm>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 int n=0,a[100001],f[100001],dp[100001];
 6 int ans=1,t=0;
 7 int main() {
 8     while(~scanf("%d",&a[++n]));
 9     n--;
10     for(int i=1; i<=n; i++) {
11         f[i]=1;
12         for(int j=t; j>0; j--)
13             if(a[i]<=a[dp[j]]) {
14                 f[i]=f[dp[j]]+1;
15                 break;
16             }
17         t=max(t,f[i]);
18         dp[f[i]]=i;
19         ans=max(ans,f[i]);
20     }
21     printf("%d\n",ans);
22     ans=1;
23     t=0;
24     for(int i=1; i<=n; i++) {
25         f[i]=1;
26         for(int j=t; j>0; j--)
27             if(a[i]>a[dp[j]]) {
28                 f[i]=f[dp[j]]+1;
29                 break;
30             }
31         t=max(t,f[i]);
32         dp[f[i]]=i;
33         ans=max(ans,f[i]);
34     }
35     printf("%d",ans);
36 }

猜你喜欢

转载自www.cnblogs.com/very-beginning/p/11953297.html