这个题可以贪心也可以动态规划
题目链接
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能超过前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹.
怎么办呢?多搞几套系统呗!你说说倒蛮容易,成本呢?成本是个大问题啊.所以俺就到这里来求救了,请帮助计算一下最少需要多少套拦截系统.
Input
输入若干组数据.每组数据包括:导弹总个数(正整数),导弹依此飞来的高度(雷达给出的高度数据是不大于30000的正整数,用空格分隔)
Output
对应每组数据输出拦截所有导弹最少要配备多少套这种导弹拦截系统.
Sample Input
8 389 207 155 300 299 170 158 65
Sample Output
2
首先,我们要确定题意,是想要最少配备多少套这种导弹拦截系统,来一个导弹我们就依次遍历所有已经开始使用的导弹,如果找到一个系统它目前拦截的最后一个(也是这个系统拦截的最低)导弹高度大于我们输入的导弹高度,那么就可以把这个导弹加入到这个导弹系统里,如果所有已有的导弹系统都不符合要求,我们就再开一个新的系统。
在给各个导弹系统加入导弹高度数据时,我们不必保存该系统每一个导弹高度,只需要保存最后一个(也就是最低的那个)就可以了。
代码如下
#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
int h[30000];//开大数组尽量声明为全局变量
int main()
{
int n;
while(scanf("%d",&n)!=EOF&&n!=0)
{
int d,num,i,j;
num=1;
scanf("%d",&d);
h[1]=d;//先将第一个系统高度安排好
n--;
while(n--)
{
scanf("%d",&d);
for(i=1;i<=num;i++)
{
if(d<h[i])//系统的每一发炮弹都不能高于前一发
{
h[i]=d;//符合要求,更新改系统高度
break;//及时跳出
}
}
if(i==num+1)//如果现有的导弹系统没有高于此高度
{
h[num+1]=d;
num++;//这个时候开了一个新系统,所以系统总数要+1
}
}
printf("%d\n",num);
}
return 0;
}
这个题其实还可以用动态规划写。所以嘛…未完待续
------------------------------2021.2.3更新---------------------------------------
动态规划来了,哈哈,时隔快一年,我来把最近刚学会的动态规划解法更新一样,这个题,其实可以转化为求最长上升子序列问题,妙啊,因为每一个高的导弹都能拦截他后面比它小的导弹,如果不能拦截,说明需要再开一个系统。
这个代码中的f[i]数组代表如果以下标为i的数字为最长子序列的最后一个元素则这个序列的长度为多少,最后我们选择f数组中的最大数就是我们要球的最长子序列了。
#include<bits/stdc++.h>//求最长有序子序列
using namespace std;
int data[99999];
int f[99999];
int cmp(int a,int b)
{
return a>b;
}
int main()
{
int n;
while(cin>>n)
{
memset(data,0,sizeof(data));
memset(f,0,sizeof(f));
for(int i=1;i<=n;i++)
cin>>data[i];
f[1]=1;
int max;
for(int i=2;i<=n;i++)
{
max=1;
for(int j=i-1;j>=1;j--)
{
if(data[i]>data[j]&&(f[j]+1>max))
{
max=f[j]+1;
}
}
f[i]=max;
}
sort(f+1,f+n+1,cmp);
cout<<f[1]<<endl;
}
return 0;
}
还有一个解法,效率更高
lower_bound是用二分法查找一定范围内大于或者等于t的数组下标,a数组就是最长子序列,之所以将t替代最长子序列中比它大的数,因为如果被替代的数刚好是序列的最后一个,那么这个序列被延长的可能性就更大,你想啊,这个最长子序列的最后一个最大数变小了,那么它后面再跟数字的可能性就增加啦。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[100005];
ll l=1,n;
int main()
{
while(cin>>n)
{
ll t;
l=1;
memset(a,0,sizeof(a));
cin>>t;
a[1]=t;
for(ll i=2;i<=n;++i)
{
cin>>t;
if(t>a[l])a[++l]=t;
else *lower_bound(a+1,a+l+1,t)=t;
}
cout<<l<<endl;
}
return 0;
}