/*
Name: 拦截导弹
Copyright:
Author:
Date: 22-07-17 22:27
Description: 题意:一种导弹拦截系统的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。
某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度,计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统?
分析:
第一问很简单,就是求最长不上升子序列,可以用高效的二分插入法。对于第二问用贪心的方法来做,
*/
#include<iostream>
#include<cstdio>
using namespace std;
const int MAX = 1000;
int A[MAX];
int S[MAX+1]; //记录到元素i为止的最长上升子序列的长度
int H[MAX]; //记录第k套系统的最小拦截高度
int Pos(int low, int high, int x);//二分法查找插入位置
void DP(int n);
int main()
{
int n;
cin >> n;
for (int i=0; i<n; i++)
{
cin >> A[i];
}
DP(n);
return 0;
}
void DP(int n) //顺序查找
{
int m = 0, k = 0, len = 0;
S[++len] = A[0];
for (int i=1; i<n; i++)
{
if (A[i] <= S[len])
{
S[++len] = A[i];
}
else //二分查找,并插入到适当位置
{
S[Pos(1, len-1, A[i])] = A[i];
}
//贪心法求系统数量,每次都用拦截高度最小的那套来拦截,若超出已有系统的最小高度,则增加一套新的系统
for (k=0; k<m; k++)//m表示目前系统的总数量,H[k]表示第k套系统,k越小,该系统的最小拦截高度越低
{
if (H[k] >= A[i])
break;
}
if (k < m)//更新第k套系统的最小拦截高度
{
H[k] = A[i];
}
else //若超出已有系统的最小高度,则增加一套新的系统,初始化其最小拦截高度为A[i]
{
H[m++] = A[i];
}
}
cout << len << endl << m << endl ;
}
int Pos(int low, int high, int x)
{
int mid;
while (low <= high)
{
mid = (low + high)/2;
if (S[mid] < x)
{
high = mid - 1;
}
else
{
low = mid + 1;
}
}
return low;
}
拦截导弹
最新推荐文章于 2023-12-23 20:13:04 发布