拦截导弹

Posted wscqwq

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了拦截导弹相关的知识,希望对你有一定的参考价值。

拦截导弹

贪心策略如下所示:图一表示具体做法,图二表示证明

上图的证明是指,如果最优解和贪心存在第一个地方不一样,那么因为 \\(a\\)\\(\\ge x\\) 的最小数,所以 \\(b\\ge a\\),所以这两段是可以互换的,所以最优解是可以变成贪心的。

性质,\\(g\\) 数组单调不降,证明如上图。

我们可以惊奇的发现,这个步骤和 896. 最长上升子序列 II 的做法一致,所以就可以用那道题的做法;这道题其实是可以用二分优化的。

#include<bits/stdc++.h>
using namespace std;
int n,x,i,j,d[500001],ans,mid,a[500001],b[500001];
int main()
	while(cin>>a[++n]);
	n--;
	for(i=n;i>=1;i--)
		b[i]=a[n-i+1];
	for(i=1;i<=n;i++)
		if(b[i]>=d[ans])
			d[++ans]=b[i];
		else
			mid=upper_bound(d+1,d+1+ans,b[i])-d;
			d[mid]=b[i];	
		
	
	cout<<ans<<endl;
	ans=0;
	for(i=1;i<=n;i++)
		if(a[i]>d[ans])
			d[++ans]=a[i];
		else
			mid=lower_bound(d+1,d+1+ans,a[i])-d;
			d[mid]=a[i];	
		
	
	cout<<ans;
	return 0;

C语言 拦截导弹

题?? - 拦截导弹

来源 计算概论2006
描述
某国为了防御敌国的导弹袭击,开发出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭,并观测到导弹依次飞来的高度,请计算这套系统最多能拦截多少导弹。拦截来袭导弹时,必须按来袭导弹袭击的时间顺序,不允许先拦截后面的导弹,再拦截前面的导弹。

关于输入
输入有两行:
第一行,输入雷达捕捉到的敌国导弹的数量k(k<=25),
第二行,输入k个正整数,表示k枚导弹的高度,按来袭导弹的袭击时间顺序给出,以空格分隔。

关于输出
输出只有一行,包含一个整数,表示最多能拦截多少枚导弹。

例子输入
8
300 207 155 300 299 170 158 65

例子输出
6

提示
无。

for (i=n-1;i>=1;i--)

for (j=n;j>=i+1;j--)

if (a[i]>a[j] && l[j]+1>l[i])

l[i]=l[j]+1;
//printf("%d %d\n",i,j);
max=0,ss=1;//for(i=1;i<=n;i++) printf("%d ",l[i]);printf("\n");
for (i=1;i<n;i++)


在这里有死循环,j永远小于i
---------------------------------------------------
/*
VC6.0编译运行成功
*/
#include
#include
/*
描述 Description
某国为了防御敌国的导弹袭击,研发出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试验阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入格式 Input Format
输入数据只有一行,该行包含若干个数据,之间用半角逗号隔开,表示导弹依次飞来的高度(导弹最多有 20 枚,其高度为不大于 30000 的正整数)。
输出格式 Output Format
输出数据只有一行,该行包含两个数据,之间用半角逗号隔开。第一个数据表示这套系统最多能拦截的导弹数;第二个数据表示若要拦截所有导弹至少要再添加多少套这样的系统。
样例输入 Sample Input
389,207,155,300,299,170,158,65
样例输出 Sample Output
6,1
其它测试输入样例
389,207,155,300,299,170,65,158
5,3,1,4,3,2,1,0
1,2,3,4,5,6,2
*/
/*
分析,问题是动态规划与Dilworth定理题目
http://www.gnocuil.cn/blog/article.asp?id=16
*/
int main()


char s[105];
int i, j, n, a[21], l[21], sign[21], max = 0, min = 0;
scanf("%s", s);
//min 代表最长递增序列长度 max 代表最短递减序列长度
for (i = 0, j = 0, a[0] = l[0] = sign[0] = 0; i < strlen(s); i++)


if (s[i] == ',')

a[++j] = 0;
sign[j] = 1;
l[j] = 1;


else

a[j] = a[j] * 10 + (s[i] - '0');


n = j;

for (i = n - 1; i >= 0; i--)

int maxflag = 0, minflag = 0;
j = i + 1;
while(j <= n)

if(a[i] > a[j])

if(l[i] < l[j])

l[i] = l[j];

maxflag = 1;

else if(a[i] < a[j])

if(sign[i] < sign[j])

sign[i] = sign[j];

minflag = 1;

j++;

if(maxflag)
l[i]++;

if(minflag)
sign[i]++;

if(max < l[i])

max = l[i];


if(min < sign[i])

min = sign[i];


printf("%d,%d\n", max, min - 1);
return (0);
参考技术A

1、求最长单调序列 简单动归(如果只求第二个的话用贪心也可以 ,不过动归可以两个一起做 而且代码更简单 )。

2、例程:

#include<stdio.h>
#include<string.h>
#define N 21
int max(int mh[],int n) /* 求最多拦截导弹数 */

   int a[N][N],b[N],i,j,k,len1,s,t;
     /*   a:各系统可能拦截导弹的高度    b:各系统拦截导弹数   */ 
     /*    s:导弹拦截系统数 */
     /* len1:可拦截当前导弹的最优系统的编号(从0开始) */
     a[0][0]=mh[0]; s=1;   b[0]=1; 
     for (i=1;i<n;i++)
     
         len1=0;   t=0; 
         for (j=0;j<s;j++) /* j:系统编号 依次考查每套系统 */
   for (k=b[j]-1;k>=0;k-- ) /* 每套系统防御导弹高度数组编号 */
   
    if (mh[i]<=a[j][k])    
    
     if (t<k+1)
      t=k+1; len1=j;   break; 
     if (t==k+1)     
      if (a[len1][t-1]>a[j][k])
       len1=j;   break;      
    
   
         if (t!=b[len1])
    /* len1系统可拦截本高度前拦截数不等于已拦截数,则新建系统 */ 
                     
             for (k=0;k<t;k++)   
    a[s][k]=a[len1][k]; /* 新建系统的各个值 */
   a[s][t]=mh[i];
   b[s]=t+1;            
             s++;   
         
         else
                                     
             a[len1][(b[len1])]=mh[i];   /* 直接接在现有高度后 */ 
             b[len1]=b[len1]+1;
         
     
     t=0;
     for (i=0;i<s;i++)
         if (b[i]>t) t=b[i];
     return t;

int min(int mh[],int num)   /* 求需最少要配备导弹拦截系统数 */

     int s[21]=0,i,j,k,p;    
     k=1;
     s[0]=mh[0];
     for (i=1;i<num;i++)
     
         p=0;
         for (j=1;j<=k;j++)
             if ( (s[j-1]>mh[i]) &&( (p==0)||(s[j-1]<s[p-1]) ) )
                p=j;/*现有系统打击范围*/ 
         if (p==0)   
             
             k++;
             s[k-1]=mh[i];
         
            else s[p-1]=mh[i];
     
     return k;

main()

     int n,mh[N],i;   /* n为导弹数,数组mh为依次飞来的高度 */
     scanf("%d",&n);   
     for (i=0;i<n;i++)
         scanf("%d",&mh[i]);
     printf("%d   %d\\n",max(mh,n),min(mh,n));;
     system("pause");
     return 0;

参考技术B 完全了解你的情况,都是被计概习题逼的啊。
这里有一个同学编的程序,虽然很小,但非常巧妙,绝对可以pass,试试看吧。
但提醒一下:pass以后,请仔细读一读这个程序,知道它为什么可以通过好吗?
#include<stdio.h>
void main()
int b[26],k,h[26],t=0,i,j;
scanf("%d",&k);
for(i=1;i<=k;i++)
scanf("%d",&h[i]);
for(i=1;i<=k;i++)
for(j=1,t=0;j<i;j++)
if(h[j]>=h[i])
if(b[j]>t)
t=b[j];
if(t==0) b[i]=1;
else b[i]=t+1;
for(i=1,t=0;i<=k;i++)
if(b[i]>t)
t=b[i];
printf("%d",t);
本回答被提问者采纳
参考技术C #include<iostream>
using namespace std;
int main()
int i,j,n,x[100],d[100]; //x[]表示各个导弹高度,d[i]记录为第 i 枚导弹被拦截之后,
//这套系统最多还能拦截的导弹数(包含被拦截的第 i 枚)。
int dmax=0,xh=0; //记录拦截的最大个数以及第一个被拦截的序号
cin>>n; //输入拦截的导弹数
for(i=0;i<n;i++)
cin>>x[i]; //输入每个导弹的高度
d[i]=1;//初始值都设为1

for(i=n-2;i>=0;i--) //动态规划算法,递归实现,从后面向前循环
for(j=i+1;j<n;j++)
if((x[j]<x[i])&&(d[i]<d[j]+1)) //判断条件
d[i]=d[j]+1;

for(i=0;i<n;i++) //找出最大个数
if(d[i]>dmax)
dmax=d[i];
xh=i;//第一枚被拦截的导弹序号


cout<<d[xh]<<endl;
cout<<x[xh]<<",";
for(j=xh+1;j<n;j++) //依次输出满足条件的递减序号
if((x[j]<=x[xh])&&(d[xh]==d[j]+1)) //判断条件
cout<<x[j]<<",";
xh=j;

system("pause");
return 0;
参考技术D 例子输入
8
300 207 155 300 299 170 158 65

输入k个正整数,表示k枚导弹的高度,按来袭导弹的袭击时间顺序给出,以空格分隔。

例子输出
6
虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。
怎么能输出6?????明显是4
你这题本身就有问题..

以上是关于拦截导弹的主要内容,如果未能解决你的问题,请参考以下文章

codevs1044 拦截导弹==洛谷 P1020 导弹拦截

导弹拦截III

导弹拦截

导弹拦截

导弹拦截

1112.拦截导弹(简单的动态规划)