最少拦截系统
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 34773 Accepted Submission(s): 13735
Problem Description
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能超过前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹.
怎么办呢?多搞几套系统呗!你说说倒蛮容易,成本呢?成本是个大问题啊.所以俺就到这里来求救了,请帮助计算一下最少需要多少套拦截系统.
Input
输入若干组数据.每组数据包括:导弹总个数(正整数),导弹依此飞来的高度(雷达给出的高度数据是不大于30000的正整数,用空格分隔)
Output
对应每组数据输出拦截所有导弹最少要配备多少套这种导弹拦截系统.
Sample Input
8 389 207 155 300 299 170 158 65
Sample Output
2
- 题意: 求解一个序列的非严格下降子序列的个数;
- 思路:主要是转化问题:对于一个序列,他的非严格下降子序列个数就是他的最长上升子序列的长度;证明:对于a1,a2,a3,a4,a5,a6,a7设最长上升子序列为a3,a5(具有唯一性)那么必有a1>=a2>a3,a4>a5>=a6>=a7,a4>a5>a3,可以推出非严格下降子序列的个数也是2,对于一般性问题也是如此:
- 失误:转化问题是这种题的关键,就是向已知的结论和模板进行转化,总能找出简单的解决方法。
- 代码如下:
#include<cstdio>
#include<vector>
using namespace std;
const int MAXN=1e4+22;
int dp[MAXN],a[MAXN];//dp[i]:以a[i]结尾的最长上升子序列
int main()
{
int N,i,j;
while(~scanf("%d",&N))
{
int ans=0;
for(i=1;i<=N;++i)
{
dp[i]=1;
scanf("%d",&a[i]);
for(j=1;j<i;++j)
{
if(a[i]>a[j]) dp[i]=max(dp[i],dp[j]+1);
}
ans=max(ans,dp[i]);//最长上升子序列不一定是以a[n]结尾的
}
printf("%d\n",ans);
}
return 0;
}
学习一下STL:
#include<cstdio>
#include<vector>
using namespace std;
int main()
{
int N,tem,i;
while(~scanf("%d",&N))
{
vector<int> VEC;
scanf("%d",&tem);
VEC.push_back(tem);
for(i=1;i<N;++i)
{
scanf("%d",&tem);
vector<int>::iterator iter=lower_bound(VEC.begin(),VEC.end(),tem);
if(iter!=VEC.end()) *iter=tem;
else VEC.push_back(tem);
}
printf("%d\n",VEC.size());
}
return 0;
}