nyoj 814 又见拦截导弹

又见拦截导弹

时间限制: 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(说的是最长子序列)。。每个栈都储存着打掉的导弹的高度。。每次一个导弹高度,我们都是在所有栈的栈顶选择一个最接近此导弹高度的,然后让此导弹高度进入到这个栈中。

而nlogn的思想感觉和这个一样的。
ans数组存的就是每个栈顶元素。而求下界也就是最接近此导弹高度的。而求下界你使用了二分查找的方法(没有使用顺序查找,当然此题二分与顺序查找只差了4ms。。但是数据要是更大感觉二分的高效就更明显了。)。当然可以证明ans数组是有序的。(当时这样想时我还以为,这应该是无序的,后来用笔画了下,问题是递推的,后面的一定比前面大。要。反证法即可)
由于本人没有看DP。。对DP算法一点也不懂。准备近期深入。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<algorithm>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<string>
#include<cstring>
#include<cmath> 
using namespace std;
/****************************
       By:七柳先森丶
       Date: 12.22 2014
*****************************/
//利用数组模拟。mn数组中保留的是每个系统中最后一次发射的高度且是最优的。。
//方法1:顺序查找。二分算法待更新。
const int mx=3001;
int mn[mx],a[mx];
int main()
{
	int n,ans;
	while(scanf("%d",&n)){
		if(n==-1) break; 
		ans=0;
		for(int i=0;i<n;i++)
			scanf("%d",&a[i]);
		mn[ans]=a[0];
		int j;
		for(int i=1;i<n;i++){
			for( j=0;j<=ans;j++){
				if(a[i]<=mn[j]){
					//此时可以证明顺序选择是最优的选择方案。 
					mn[j]=a[i];
					break;
				}
			}
			//当前没有合适的系统。新增。 
			if(j == (ans+1)){
				mn[ans+1]=a[i];
				ans++;
			}
			 
		}
		printf("%d\n",ans+1);
	} 
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值