nyoj 79 导弹拦截 & hdu 1257 最少拦截系统

nyoj 79 导弹拦截

时间限制:3000 ms  |  内存限制:65535 KB
描述
  某国为了防御敌国的导弹袭击,发展中一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于等于前一发的高度。某天,雷达捕捉到敌国导弹来袭。由于该系统还在试用阶段,所以只用一套系统,因此有可能不能拦截所有的导弹。
输入
  第一行输入测试数据组数N(1<=N<=10) 接下来一行输入这组测试数据共有多少个导弹m(1<=m<=20) 接下来行输入导弹依次飞来的高度,所有高度值均是大于0的正整数。输出
  输出最多能拦截的导弹数目
样例输入
  2
  8
  389 207 155 300 299 170 158 65
  3
  88 34 65
样例输出
  6
  2
  经典DP,问题具有最优子结构特性,最多能拦截导弹的数目即为该串最长不增子序列的长度,对于高度序列h,对于其中的某一个高度h[i],若其后有有长为w的最长不增子序列h[j..n],则串h[i...j...n]的最长不增子序列的长度为w+1.有次得到递归方程:
  dp[n]=1;(dp记录最长不增子序列的长度,串长为n)
  dp[i]=max(dp[j])+1;(i<j<=n 且 h[i]>h[j])
  最后输出最长子序列的长度即可
 1 #include<stdio.h>
 2 
 3 int main()
 4 {
 5     int n,m,i,j,max,h[21],dp[21];
 6     scanf("%d",&n);
 7     while(n--)
 8     {
 9         max=0;
10         scanf("%d",&m);
11         for(i=0;i<m;i++)
12         {
13             scanf("%d",&h[i]);
14             dp[i]=1;
15         }
16 
17         for(i=m-2;i>=0;i--)
18         {
19             for(j=i+1;j<m;j++)
20             {
21                 if(h[i]>h[j] && dp[i]<dp[j]+1)
22                     dp[i]=dp[j]+1;
23             }
24             if(dp[i]>=max) max=dp[i];
25         }
26         printf("%d\n",max);
27     }
28     return 0;
29 }

hdu 1257 最少拦截系统

问题描述

某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能超过前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹. 怎么办呢?多搞几套系统呗!你说说倒蛮容易,成本呢?成本是个大问题啊.所以俺就到这里来求救了,请帮助计算一下最少需要多少套拦截系统

输入

输入若干组数据.每组数据包括:导弹总个数(正整数),导弹依此飞来的高度(雷达给出的高度数据是不大于30000的正整数,用空格分隔)

输出

对应每组数据输出拦截所有导弹最少要配备多少套这种导弹拦截系统

样例输入

8 389 207 155 300 299 170 158 65

样例输出

2

  作这个题时严重受到上一个题的影响,认为若使用的系统数最少则每一套系统应拦截的导弹数尽可能的多,这样的想法是不对的,因为上一个题的要求是全局最优(一套系统尽可能多的拦截导弹),但是本题不但要全局最优(用的系统数最少)还要保证局部安全(不能放过任何一颗导弹).举一个反例,对于长为7的高度序列“7 5 4 1 6 3 2”, 最长不增序列为“7 5 4 3 2”,用多次求最长不上升序列的结果为3套系统;但其实只要2套,分别击落“7 5 4 1”与“6 3 2”。所以本体需要一种"贪心"的策略来保证局部安全.先给出代码.

 1 #include<stdio.h>
 2 
 3 int main()
 4 {
 5     int n,tot,i,j,t,h[1005];
 6     while(scanf("%d",&n)!=EOF)
 7     {
 8         scanf("%d",&t);
 9         h[0]=t; tot=1;
10         for(i=1;i<n;i++)
11         {
12             scanf("%d",&t);
13             for(j=0;j<tot;j++)
14                 if(t<h[j])
15                 {
16                     h[j]=t;
17                     break;
18                 }
19             if(j>=tot) h[tot++]=t;
20         }
21         printf("%d\n",tot);
22     }
23     return 0;
24 }

对于本体的高度序列h,若h[i]大于之前的任何元素,则必须新增一套系统,拦截之后该系统的最大高度为h[i].若h[i]不全大于之前的任意元素,则应选取恰比其大的系统拦截它,拦截之后系统的高度降为h[i].在程序中一次读入导弹高度数据,若其大于之前的任意高度将其放入数组h并将系统数量+1,否则找到当前系统中大于其高度最小的并替换.在构建h数组的过程中h数组自然升序.在查找时也可使用二分法提高效率.

转载于:https://www.cnblogs.com/code-maker/p/3354378.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值