时间限制 | 1000ms | 空间限制 | 32768KB |
题目:
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能超过前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹.
怎么办呢?多搞几套系统呗!你说说倒蛮容易,成本呢?成本是个大问题啊.所以俺就到这里来求救了,请帮助计算一下最少需要多少套拦截系统.
输入:
输入若干组数据.每组数据包括:导弹总个数(正整数),导弹依此飞来的高度(雷达给出的高度数据是不大于30000的正整数,用空格分隔)
输出:
对应每组数据输出拦截所有导弹最少要配备多少套这种导弹拦截系统.
样例输入:
8 389 207 155 300 299 170 158 65
样例输出:
2
题意:给出n个导弹,要用导弹系统去拦截这些导弹,但是一个拦截系统每次发出的拦截导弹不会超过前面发出的导弹,求最少要用多少个拦截导弹系统。
思路:dp求不下降子序列或者暴力求解。
dp求不下降子序列的代码:
#include <bits/stdc++.h>
using namespace std;
//连续非递减最长子序列的长度 O(n^2)算法,其实还可以有O(n*logn)算法
//本算法是O(n^2)
/*
对于长度为N的数组A[N] = {a0, a1, a2, …, an-1},假设我们想求以aj结尾的最大递增子序列长度,
设为L[j],那么L[j] = max(L[i]) + 1, where i < j && a[i] < a[j], 也就是i的范围是0到j – 1。
这样,想求aj结尾的最大递增子序列的长度,我们就需要遍历j之前的所有位置i(0到j-1),找出a[i] < a[j],
计算这些i中,能产生最大L[i]的i,之后就可以求出L[j]。
之后我对每一个A[N]中的元素都计算以他们各自结尾的最大递增子序列的长度,这些长度的最大值,就是我们要求的问题
——数组A的最大递增子序列。
*/
const int N=1005;
int num[N],dp[N],n;
int solve()
{
for(int i=1;i<=n;i++) //初始化为1,本身就是一个最小的子序列(长度为1)
dp[i]=1;
for(int i=2;i<=n;i++)
{
for(int j=1;j<=i-1;j++)
{
if(num[j]<=num[i])
dp[i]=max(dp[i],dp[j]+1);
}
}
return *max_element(dp+1,dp+1+n); //返回数组num中的最大值,注意前面的*
}
int main()
{
while(cin>>n) //输入数据有多组
{
for(int i=1;i<=n;i++)
cin>>num[i];
cout<<solve()<<endl;
}
return 0;
}
暴力求解:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int a[100000],b[100000];
int main()
{
int n,t,j;
while(cin>>n)
{
memset(b,0,sizeof(b));
for(int i=0;i<n;i++)
cin>>a[i];
for(j=1;;j++)
{
for(int s=0;s<n;s++)
if(b[s]==0)
{
t=s;
b[t]=-1;
break;
}
for(int i=1;i<n;i++)
{
if(a[t]<a[i]||b[i]==-1)
continue;
else
{
t=i;
b[t]=-1;
}
}
if(*max_element(b,b+n)==-1)
break;
}
cout<<j<<endl;
}
}