問題描述:
某國爲了防禦敵國的導彈襲擊,發展出一種導彈攔截系統。但是這種導彈攔截系統有一個缺陷:雖然它的第一發炮彈能夠達到任意的高度,但是以後每一發炮彈都不能高於前一發的高度。某天,雷達捕捉到敵國的導彈來襲。由於該系統還在使用階段,所以只有一套系統,因此有可能不能攔截所有的導彈。
輸入導彈依次飛來的高度(雷達給出高度數據是不大於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
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
問題分析
第一問可以抽象爲,求一組數列的最長降序列。設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();
}