问题描述:
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够达到任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在使用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出高度数据是不大于30000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹系统。
样例:
Input: 389 207 155 300 299 170 158 65
Output: 6(最多拦截导弹数)
2(要拦截所有导弹最少要配备的系统数)
运行示例:
INPUT: 300 250 275 252 200 138 245
OUTPUT: 5 2
INPUT: 181 205 471 782 1033 1058 1111
OUTPUT: 1 7
INPUT: 465 978 486 324 575 384 278 214 657 218 445 123
OUTPUT: 6 4
INPUT: 236 865 858 565 545 445 455 656 844 735 638 652 569 714 845
OUTPUT: 6 7
问题分析
第一问可以抽象为,求一组数列的最长降序列。设st(n)为数组中以第n个数为头的最长递减序列长度。st(n-1)=max(st(x1),st(x2)...st(xi))+1. 其中n<=xi<=N,并且数组中第xi个数要小于第n-1个数。可以用递归。
第二问:用链表存储n个高度。先找链表中最大的数,并纪录最大数的下一个位置t,删除那个最大的数。再从t开始找最大的数,再纪录再删除。直到t为表尾,结束一轮。系统数加1。再从表头开始重复上一步,直到链表为空。
例如:7 6 2 8 5 3
先找到8,删除8。再从5开始找,5最大删除。再从3开始,3为表尾删除,并结束一轮。
再从表头7开始找,删除7,6,2后表为空。停止 系统即:8 5 3和7 6 2
第二问的算法可以用一个有向无环图来证明。
数据结构
第一问用数组存储n个高度。程序中用high[]这个数组。
第二问用带头结点的单链表来储存n个数字。
typedef struct Node
{
int val;
struct Node *next;
}Node,*Link;
程序清单
#include <stdio.h>
#define N 100
int high[N+1]={0};
int k=0;
int system=0;
int NoMaxSq(int n)
{
int i,max;
if(n==k)
return 1;
else
{
max=0;
for(i=n+1;i<=k;i++)
{
if(high[i]<high[n])
max=NoMaxSq(i);
break;
}
for(i=n+1;i<=k;i++)
{
if(high[i]<high[n])
if(NoMaxSq(i)>max)
max=NoMaxSq(i);
}
return max+1;
}
}
typedef struct Node
{
int val;
struct Node *next;
}Node,*Link;
Node *PriorElem(Link L,Node *t)
{
Node *p=L;
while((p!=0)&&(p->next!=t))
p=p->next;
return p;
}
void SystemNo()
{
int i,max;
Node *p,*t,*q;
Node *mp,*temp;
Link L;
L=(Link) malloc(sizeof(Node));
L->next=NULL;
for(i=k;i>0;--i)
{
p=(Link)malloc(sizeof(Node));
p->val=high[i];
p->next=L->next;L->next=p;
}
do
{
t=L->next;
do
{
q=PriorElem(L,t);
for(max=t->val;t;q=t,t=t->next)
if(max<=t->val)
{
max=t->val;
temp=t;
mp=q;
}
mp->next=temp->next;
free(temp);
t=mp->next;
}while(t);
++system;
}while(L->next);
}
main()
{
void SystemNo();
int i=0,n=0;
int max;
char c;
char s[100];
while((c=getchar())!='/n')
{
s[i++]=c;
}
s[i]='/0';
i=0;
while(s[i]!='/0')
{
if(s[i]==' ')
i++;
for(;s[i]>='0'&&s[i]<='9';++i)
n=10*n+(s[i]-'0');
high[++k]=n;
n=0;
}
max=0;
for(i=1;i<=k;i++)
if(max<NoMaxSq(i))
max=NoMaxSq(i);
printf("%d",max);
SystemNo();
printf(" %d",system);
getch();
}