又见拦截导弹
时间限制:
3000 ms | 内存限制:
65535 KB
难度:
3
-
描述
-
大家对拦截导弹那个题目应该比较熟悉了,我再叙述一下题意:某国为了防御敌国的导弹袭击,新研制出来一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能超过前一发的高度。突然有一天,雷达捕捉到敌国的导弹来袭。由于该系统存在缺陷,所以如果想把所有的导弹都拦截下来,就要多准备几套这样的导弹拦截系统。但是由于该系统成本太高,所以为了降低成本,请你计算一下最少需要多少套拦截系统。
-
输入
-
有多组测试数据。
每组数据先输入一个整数N(N≤3000),代表有N发导弹来袭。接下来有N个数,分别代表依次飞来的导弹的导弹的高度。当N=-1时表示输入结束。
输出
- 每组输出数据占一行,表示最少需要多少套拦截系统。 样例输入
-
8 389 207 155 300 299 170 158 65 5 265 156 123 76 26
样例输出
-
2
1
-
-
**思路:求单调递减序列的个数,
-
但看了别人的思路后,我发现反过来求的最长单调递增数列的长度就是答案,至于为什么,现在还是似懂非懂,先写下,来日方长慢慢看
-
方法上可以用DP也可以不用
-
1,dp版本
-
其中的 dp[i] 表示以 arr[i]为结尾的单调递减序列的长度,
-
dp[i] = max{dp[i],dp[j]+1};(动态转移方程)
-
具体意思我说不清,见参考书 挑战程序设计 p64 下
-
-
-
#include <iostream> #include <algorithm> using namespace std; int main() { int n,i,j; while(cin>>n&&n!=-1) { int arr[n],dp[n+3]; for(i=0;i<n;i++) { cin>>arr[i]; dp[i] = 1; } for(i=0;i<n;i++) { for(j=0;j<i;j++) { if(arr[i]>arr[j])//由递推公式的来的 dp[i] = max(dp[i],dp[j]+1); } } int themax = 0; for(i=0;i<n;i++) { if(dp[i]>themax) themax = dp[i]; } cout<<themax<<endl; } return 0; }
2,
另一种高能的算法,也是书上的,效率是上面dp的100倍!! -
也是那页书后面的,更说不好说,自己看吧,这才是乐趣
-
#include <iostream> #include <algorithm> const int INF = 0x6ffffff; using namespace std; int main() { int n,i,j,themax; while(cin>>n&&n!=-1) { int arr[n],dp[n+3]; themax = 0; for(i=0;i<n;i++) { cin>>arr[i]; } fill(dp,dp+n+3,INF); for(i=0;i<n;i++) { int *p = lower_bound(dp,dp+n,arr[i]); *p = arr[i]; } cout<<lower_bound(dp,dp+n+3,INF)-dp<<endl; } return 0; }
-
奈何我冒泡的算法如何打动你超时的心!!
-
-
有多组测试数据。