1020 导弹拦截
难度:普及/提高-
题目类型:动规
提交次数:1
涉及知识:线性动规
题目描述
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入输出格式
输入格式:
一行,若干个正整数。
输出格式:
2行,每行一个整数,第一个数字表示这套系统最多能拦截多少导弹,第二个数字表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
代码:
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 int a[10005]; 5 int d[10005]; 6 int main(){ 7 int i, j, n = 0; 8 d[0] = 1; 9 while(cin>>a[n]){ 10 n++; 11 d[n] = 1; 12 } 13 14 for(i = 0; i < n; i++) 15 for(j = 0; j < i; j++) 16 if(a[i]<a[j]) 17 d[i] = max(d[i], d[j]+1); 18 int ans = 0; 19 for(i = 0; i < n; i++) 20 ans = max(ans, d[i]); 21 cout<<ans<<endl; 22 23 for(i = 0; i < n; i++) d[i] = 1; 24 ans = 0; 25 26 for(i = 0; i < n; i++) 27 for(j = 0; j < i; j++) 28 if(a[j]<a[i]) 29 d[i] = max(d[i], d[j]+1); 30 for(i = 0; i < n; i++) 31 ans = max(ans, d[i]); 32 cout<<ans<<endl; 33 return 0; 34 }
备注:
第二问是难点。题解里说到可以转化为求最长上升子序列,然而我想了一天也不知道为什么。看到有一个博主这样解释“……这个子序列里的每一个导弹都不可能用同一个拦截系统拦下……”,也就是说每一个导弹都得单用一套系统,这个倒很好理解。那为什么在这个序列之外的都可以跟这个序列里的某一枚导弹合用一套系统呢?我充分利用了一下我们上数学自招课培养的思维方法(……)分析了一下。从反面想可以理解,这个序列之外的数总能在它之前找到一个序列内比它大 或 在它之后序列内比它小的数,它跟人家就可以共用。从反面想,如果存在一序列外的导弹,它之前的序列内所有数都比它小,它之后序列内所有数都比它大,那它一定在最长上升子序列内。与在序列外的假设矛盾。
哇塞我这个反证证得真漂亮。表扬一下自己,这课真没白上。
然而并没有什么卵用。从正面想我根本不可能想出来。