最少拦截系统

方法一:贪心算法 

导弹的高度来决定拦截系统的高度,
每次更新已存在的拦截系统的高度,
如果没有大于等于导弹高度的拦截系统,
就再添加一个新的拦截系统。

代码实现:

#include<iostream>
#include<cstring>
using namespace std;
int a;
int b[100010];
int main()
{
	int n,m;
	while(scanf("%d",&n)!=EOF)
	{
		memset(b,0,sizeof(b));//初始化数组 
		m=0;//拦截系统的个数 
		for(int i=0;i<n;i++)
		{
			cin>>a;
			int j; 
			for(j=0;j<=m;j++)//每次用较小的拦截系统来替换b中的数 
			{
				if(b[j]>=a)
				{
					b[j]=a;
					break;
				}
			}
			if(j>m)//如果所有的拦截系统都不能拦截 
			{
				b[++m]=a;//因为每次都是先遍历,再往后追加所以b数组中的数是从小到大排列的 
			}
		}
		cout<<m<<endl;
	}
	return 0;
 }

附加:贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。 

方法二:DP算法

这个题实际上就是求原序列的LIS(最长递增子序列),根据题意,我们可以先自己模拟一下拦截导弹的过程,然后定义状态dp[i](代表以第i个数为结尾的最长递增子序列的长度,也表示有多少个递减子序列)及dp[i]=max{0,dp[j]+1},0<j<i。答案为max{dp[i]}.


代码实现:

# include<stdio.h>
# include<algorithm>
# include<iostream>
# include<cstring>
using namespace std;
int dp[10050],h[10050];
int main()
{
	int n;
	while(~scanf("%d",&n))
	{
		memset(dp,0,sizeof dp);
		for(int i=1;i<=n;i++)
			cin>>h[i];
		int sum=0,max;
		dp[1]=1;
		for(int i=1;i<=n;i++)
		{
			max=0;
			for(int j=1;j<=i;j++)
			{
				if(h[j]<h[i]&&max<dp[j])
				{
					max=dp[j];
				}
				dp[i]=max+1;
			}
		}
		for(int i=1;i<=n;i++)
		{
			if(dp[i]>sum)
			sum=dp[i];
		}
		cout<<sum<<endl;
	}
	return 0;
 } 

方法三:利用序列本身的性质通过一个辅助数组统计最长递增子序列的长度

这题可以单纯的看成dp求最长的递增序列长度(POJ 2533)的计算,大概就是先用数组定义所有的数字本来是自己包含的最长有序子列长度为1,然后用for循环来判断某个数字和它前面的数字的大小情况。如果是小于这个数的话,记录++;然后再先一个循环求出最长的那个序列
代码实现:

# include<stdio.h>
# include<iostream>
# include<algorithm>
# include<cstring>
using namespace std;
int main()
{
	int n,f[1050],dp[1050];
	while(~scanf("%d",&n))
	{
		memset(dp,0,sizeof dp);
		for(int i=1;i<=n;i++)
			cin>>f[i];
		for(int i=1;i<=n;i++)
		{
			dp[i]=1;
			for(int j=1;j<=i;j++)
			{
				if(f[j]<f[i])
					dp[i]=max(dp[i],dp[j]+1);
			}
		}
		int ans=-1;
		for(int i=1;i<=n;i++)
		{
			if(ans<dp[i])
			ans=dp[i]; 
		}	
	cout<<ans<<endl;	
	}
	return 0;
}

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值