1044_拦截导弹

/*
	Name: 
	Copyright: 1044_拦截导弹
	Author: 
	Date: 08-08-17 14:50
	Description: 1044_拦截导弹  1999年NOIP全国联赛提高组
 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 黄金 Gold
 题解
题目描述 Description
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。
但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。
某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入描述 Input Description
输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数)
输出描述 Output Description
输出这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

样例输入 Sample Input
389 207 155 300 299 170 158 65 
样例输出 Sample Output
6(最多拦截导弹数)
2(要拦截所有导弹最少要配备的系统数)

数据范围及提示 Data Size & Hint
导弹的高度<=30000,导弹个数<=20
分析:
第一问很简单,就是求最长不上升子序列,可以用高效的二分插入法。对于第二问用贪心的方法来做,
*/
#include <iostream>

using namespace std;

const int MAX = 20; 
int A[MAX];
int S[MAX]; //记录到元素i为止的最长上升子序列的长度 
int H[MAX]; //记录第k套系统的最小拦截高度 

void DP(int n); //顺序查找 

int main() 
{
	int n = 0;
	while (cin >> A[n])
	{
		n++;
	}
	
	DP(n);
	
    return 0;
}

void DP(int n) //顺序查找 
{
	int ans1 = 1, ans2 = 0, k = 0;  
	
	for (int i=0; i<n; i++)
	{
		S[i] = 1; //默认到元素i为止的最长上升子序列的长度为1 
		for (int j=i-1; j>=0; j--)//逆序查找不大于A[i],且最长的元素,找到后更新S[i]和m的值
		{
			if (A[i] <= A[j] && S[j] >= S[i])
			{
				S[i] = S[j] + 1;
				if (S[i] > ans1) 
					ans1 = S[i];
			}
		}
		//贪心法求系统数量,每次都用拦截高度最小的那套来拦截,若超出已有系统的最小高度,则增加一套新的系统
		for (k=0; k<ans2; k++)//ans2表示目前系统的总数量,H[k]表示第k套系统,k越小,该系统的最小拦截高度越低 
		{
			if (H[k] >= A[i])
				break;
		}
		
		if (k < ans2)//更新第k套系统的最小拦截高度 
			H[k] = A[i];
		else //若超出已有系统的最小高度,则增加一套新的系统,初始化其最小拦截高度为A[i] 
			H[ans2++] = A[i];
	}
	cout << ans1 << endl << ans2 << endl ;
}

/*
	Name: 
	Copyright: 1044_拦截导弹
	Author: 
	Date: 08-08-17 14:50
	Description: 1044_拦截导弹  1999年NOIP全国联赛提高组
 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 黄金 Gold
 题解
题目描述 Description
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。
但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。
某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入描述 Input Description
输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数)
输出描述 Output Description
输出这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

样例输入 Sample Input
389 207 155 300 299 170 158 65 
样例输出 Sample Output
6(最多拦截导弹数)
2(要拦截所有导弹最少要配备的系统数)

数据范围及提示 Data Size & Hint
导弹的高度<=30000,导弹个数<=20
分析:
第一问很简单,就是求最长不上升子序列,可以用高效的二分插入法。对于第二问用贪心的方法来做,
*/
#include <iostream>

using namespace std;

const int MAX = 20; 
int A[MAX];
int S[MAX]; //记录到元素i为止的最长上升子序列的长度 
int H[MAX]; //记录第k套系统的最小拦截高度 

void DP(int n); //顺序查找 

int main() 
{
	int n = 0;
	while (cin >> A[n])
	{
		n++;
	}
	
	DP(n);
	
    return 0;
}

void DP(int n) //顺序查找 
{
	int ans1 = 1, ans2 = 1;
	
	for (int i=0; i<n; i++)
	{
		S[i] = H[i] = 1;
		for (int j=i-1; j>=0; j--)
		{
			if (A[i] <= A[j])
			{
				S[i] = max(S[i], S[j]+1);
				ans1 = max(ans1, S[i]);
			}
			else
			{
				H[i] = max(H[i], H[j]+1);
				ans2 = max(ans2, H[i]);
			}
		}
	}
	cout << ans1 << endl << ans2 << endl ;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值