题目:[NOIP1999]拦截导弹(最长非递增子序列DP) O(n^2)和O(n*log(n))的两种做法
题目:[NOIP1999]拦截导弹
问题编号:217
题目描述
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入格式
输入数据为两行,
第一行为导弹的数目N(n<=1000)
第二行导弹依次飞来的高度,所有高度值均为不大于30000的正整数。
输出格式
输出只有一行是这套系统最多能拦截的导弹数和要拦截所有导弹最少要配备这种导弹拦截系统的套数。两个数据之间用一个空格隔开.
样例输入
样例输出
题意:
见上。
思路:
首先说容易想到的o(n^2)的算法。dp[i]表示以第i个导弹结尾的最长非递增子序列。
那么dp[i]=max(dp[j]+1).bom[j]>=bom[i]。j<i。bom[i]表示第i个导弹的高度。
然后遍历dp[]找最大值即可。
对于拦截的所有导弹的最少系统数。贪心思想。能拦截就用最小射程的系统拦截。不能拦就新开一个系统。
考虑到导弹的射程满足单调性。可以二分查找。详细见代码:
#include <iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int dp[1010],hei[1010],bom[1010],cnt;
void addf(int h)
{
int l,r,mid,ans=-1;
l=0,r=cnt-1;
while(l<=r)
{
mid=(l+r)>>1;
if(hei[mid]>=h)
ans=mid,r=mid-1;
else
l=mid+1;
}
if(ans==-1)
hei[cnt++]=h;
else
hei[ans]=h;
}
int main()
{
int i,j,n,ans; while(~scanf("%d",&n))
{
cnt=0;
for(i=1;i<=n;i++)
{
scanf("%d",bom+i);
addf(bom[i]);
}
dp[1]=ans=1;
for(i=2;i<=n;i++)
{
dp[i]=1;
for(j=1;j<i;j++)
if(bom[j]>=bom[i])
dp[i]=max(dp[i],dp[j]+1);
}
for(i=2;i<=n;i++)
ans=max(ans,dp[i]);
printf("%d %d\n",ans,cnt);
}
return 0;
}
对于o(n*log(n))的算法。最少系统数仍然二分。对于一个系统可以拦截最多导弹数要换一种思路。
我们用dp[i]表示拦截导弹数为i系统的最大射程。对于bom[i]我们找到最大的j使得dp[j]>=bom[i]。那么
dp[j+1]=max(dp[j+1],bom[i])。感觉有点贪心的思想。同样的长度使结尾最大以给后面留更多的选择余地。
详细见代码:
#include <iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int dp[1010],hei[1010],bom[1010],cnt,len;
void addf(int h)
{
int l,r,mid,ans=-1;
l=0,r=cnt-1;
while(l<=r)
{
mid=(l+r)>>1;
if(hei[mid]>=h)
ans=mid,r=mid-1;
else
l=mid+1;
}
if(ans==-1)
hei[cnt++]=h;
else
hei[ans]=h;
}
void binf(int x)
{
int l,r,mid,ans=-1;
l=1,r=len;
while(l<=r)
{
mid=(l+r)>>1;
if(dp[mid]>=x)
{
ans=mid;
l=mid+1;
}
else
r=mid-1;
}
if(ans>0)
{
dp[ans+1]=max(dp[ans+1],x);
if(ans+1>len)
len++;
}
else if(r<l)
dp[1]=x;
}
int main()
{
int i,n; while(~scanf("%d",&n))
{
cnt=0;
for(i=1;i<=n;i++)
{
scanf("%d",bom+i);
addf(bom[i]);
}
dp[1]=bom[1];
len=1;
for(i=2;i<=n;i++)
binf(bom[i]);
printf("%d %d\n",len,cnt);
}
return 0;
}
题目:[NOIP1999]拦截导弹(最长非递增子序列DP) O(n^2)和O(n*log(n))的两种做法的更多相关文章
- 动态规划-最长单调递增子序列(dp)
最长单调递增子序列 解题思想:动态规划 1.解法1(n2) 状态:d[i] = 长度为i+1的递增子序列的长度 状态转移方程:dp[i] = max(dp[j]+1, dp[i]); 分析:最开始把d ...
- 588. [NOIP1999] 拦截导弹
588. [NOIP1999] 拦截导弹 ★ 输入文件:missile.in 输出文件:missile.out 简单对比 时间限制:1 s 内存限制:128 MB 题目描述 某国为了防御敌国的导 ...
- HDU 5532 Almost Sorted Array (最长非递减子序列)
题目链接 Problem Description We are all familiar with sorting algorithms: quick sort, merge sort, heap s ...
- HDU 6357.Hills And Valleys-字符串非严格递增子序列(LIS最长非下降子序列)+动态规划(区间翻转l,r找最长非递减子序列),好题哇 (2018 Multi-University Training Contest 5 1008)
6357. Hills And Valleys 自己感觉这是个好题,应该是经典题目,所以半路选手补了这道字符串的动态规划题目. 题意就是给你一个串,翻转任意区间一次,求最长的非下降子序列. 一看题面写 ...
- HDURevenge of Segment Tree(第二长的递增子序列)
HDURevenge of Segment Tree(第二长的递增子序列) 题目链接 题目大意:这题是求第二长的递增子序列. 解题思路:用n^2的算法来求LIS,可是这里还要记录一下最长的那个序列是否 ...
- 最长非降子序列的O(n^2)解法
这次我们来讲解一个叫做"最长非下降子序列"的问题及他的O(n^2)解法. 首先我们来描述一下什么是"最长非下降子序列". 给你一个长度为n的数组a,在数组a中顺 ...
- [LeetCode] Longest Uncommon Subsequence I 最长非共同子序列之一
Given a group of two strings, you need to find the longest uncommon subsequence of this group of two ...
- [ACM_动态规划] UVA 12511 Virus [最长公共递增子序列 LCIS 动态规划]
Virus We have a log file, which is a sequence of recorded events. Naturally, the timestamps are s ...
- Educational Codeforces Round 97 (Rated for Div. 2) E. Make It Increasing(最长非下降子序列)
题目链接:https://codeforces.com/contest/1437/problem/E 题意 给出一个大小为 \(n\) 的数组 \(a\) 和一个下标数组 \(b\),每次操作可以选择 ...
随机推荐
- Rolling cURL: PHP并发最佳实践
Rolling cURL: PHP并发最佳实践 在实际项目或者自己编写小工具(比如新闻聚合,商品价格监控,比价)的过程中, 通常需要从第3方网站或者API接口获取数据, 在需要处理1个URL队列时, ...
- c - 字符串的拼接.
完整代码: #include <stdio.h> #include <string.h> #include <malloc.h> #define TRUE 1 #d ...
- phpcms 2008和discuz X3.1实现同步登陆退出论坛(已实现)
网络上文章很多,按步骤配置好了之后phpcms可以同步登录dz,但是dz登录后状态却无法同步到phpcms,网络上找了很多资料都大同小异,头大.只能自己调试了,废话不多说了. 以下网络上抄 ...
- bat转向指定的目录路径处
使用bat命令转到指定的盘符路径: cd /d xxxx目录路径. 例如:cd /d D:\abc\efg 则是转到D盘的abc目录下的efg目录处.其中 /d 是指:无论当前bat是在哪个盘符中,都 ...
- php错误处理和php异常处理机制
php错误处理 当我们开发程序时,有时候程序出现了问题,我们就可以用以下几种办法找出错误. 开发阶段:开发时输出所有的错误报告,有利于我们进行程序调试 运行阶段:我们不要让程序输出任何一种错误报 ...
- java反射 -Class类
Class类:任何类都是Class类的对象 Class类的实例对象的三种表现形式:1.通过某个类的.class实现 2.某个类的对象的getClass()方法 3.Class.forName() 注意 ...
- 基于verilog的FPGA编程经验总结(XILINX ISE工具)
1.用ISE仿真的时候.所用变量一定要初始化. ISE默认初始量为"XXXXX", 而Quarters是默认为"00000"的, 其实实际上, 下到FPGA里后 ...
- C# 文件创建时间,修改时间
System.IO.FileInfo fi = new System.IO.FileInfo(@"D:\site\EKECMS\skin\Grey\default#.html"); ...
- Android实现三级联动下拉框 下拉列表spinner
Android实现(省.市.县)三级联动下拉框 下拉列表spinner 转载请注明出处: http://www.goteny.com/articles/2013/11/46.html http://w ...
- 监视系统3389的VBS脚本
Title: 监视系统3389的VBS脚本 --2010-10-27 19:56 从网上找的,不知道是不是NP写的那个 ---------------------------------------- ...