HDU 1257 最少拦截系统+NYOJ 79 拦截导弹

30 篇文章 0 订阅
11 篇文章 0 订阅

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1257

这段时间在做专题训练,所以就刻意挑了挑动态规划做。

题目一看就知道是跟最长单调递减类似,简单的动态规划。

代码:

#include<stdio.h>//**dp[i]表示第i个导弹飞过来时需要的最少拦截装置.**//
int main()
{
    int n,i,j,max,h[10001],dp[10001];
    while(~scanf("%d",&n))
    {
        max=-1;
		dp[0]=0;
        for(i=1;i<=n;i++)
        {
            scanf("%d",&h[i]);//**飞来的高度**//
            dp[i]=1;//**初始化拦截装置都为1**//
        }
        for(i=1;i<=n;i++)
        {
            for(j=i-1;j>=0;j--)
            {
                if(h[i]>h[j]&&dp[i]<dp[j]+1)//**如果在拦截中出现了非单调递减的**//
                {
                    dp[i]=dp[j]+1;
                }
            }
        }
        for(i=1;i<=n;i++)
        {
            if(dp[i]>max)
            {
                max=dp[i];
            }
        }
        printf("%d\n",max);
    }
    return 0;
}


还可以用贪心来做,其实方法还是类似的,找了段便于理解的解释就直接贴出来了。对于这个题目的测试例的解释:当8枚导弹依次飞来时,对于前三枚导弹(300207155),用第一套系统即可拦截,每一次更新记录,即:对第一枚导弹直接拦截,第二枚导弹来临时也用第一套系统拦截,记录改变成207,当用第一套系统拦截第三枚后记录修改为155,当第四枚导弹来时按照系统规定,第一套系统无法实现对第四枚导弹的拦截任务,因此,开第二套系统,为了使用最少系统,必须对以后的每一枚导弹贪心,即:拿这枚导弹和以前的导弹最小记录依次做比较,寻找一个和这枚导弹高度最接近的记录并用这枚导弹的高度替换原记录,最后记录数组中的个数就是最少需要的系统数。

其实在纸上写写就会发现以前导弹的最小记录按拦截记录来比较都是最小的。意思就是假如前面的拦截装置能够拦截就一定不需要判断后面的是否需要拦截,一定不需要拦截,依次类推(贪心);

代码:

#include<stdio.h>
int main()
{
    int n,x,i,j,min,count,flag,a[10001];
    while(~scanf("%d",&n))
    {
        count=0;
        for(i=1;i<=n;i++)
        {
            flag=0;//***标记元素**//
            scanf("%d",&x);
            min=30005;
            for(j=0;j<=count-1;j++)
            {
                if(a[j]>x&&min>a[j]-x)//**保证是和这个导弹最接近的**//
                {
                    min=a[j]-x;
                    a[j]=x;
                    flag=1;
                }
            }
            if(flag==0)
            {
                a[count]=x;
                count++;
            }
        }
        printf("%d\n",count);
    }
    return 0;
}
还有一题差不多的,直接求单调递减的最大个数。

题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=79

直接上代码:

 
 
#include<stdio.h>
int main()
{
	int s,n,i,j,max,h[101],dp[101];
	scanf("%d",&s);
	while(s--)
	{
		max=-1;
		dp[0]=0;
		scanf("%d",&n);
		for(i=0;i<=n-1;i++)
		{
			scanf("%d",&h[i]);
			dp[i]=1;
		}
		for(i=1;i<=n-1;i++)
		{
			for(j=i-1;j>=0;j--)
			{
				if(h[i]<h[j]&&dp[i]<dp[j]+1)
				{
					dp[i]=dp[j]+1;
				}
			}
		}
		for(i=0;i<=n-1;i++)
		{
			if(dp[i]>max)
			{
				max=dp[i];
			}
		}
		printf("%d\n",max);
	}
	return 0;
}                





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值