想看更多的解题报告: http://blog.csdn.net/wangjian8006/article/details/7870410
转载请注明出处:http://blog.csdn.net/wangjian8006
Description
某国为了防御敌国的导弹袭击,开发出了一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
Input
输入的第一行为测试用例的个数k(k<50)。
对于每个测试用例,包含2行数据,第一行包含一个正整数n(0<n<=50),表示导弹的个数,其后一行中包含n个导弹依次飞来的高度,所有高度值均为不大于30000的正整数。
Output
对于每个测试用例,有如下三行输出:
第一行输出在拦截导弹最多情况下的所拦截的导弹高度,如果存在多个这样的序列,则输出最大值序列。例如,有如下两个序列:"90 80 70","90 75 70",那么最大值序列应该取"90 80 70"。
第二行输出这套系统最多能拦截的导弹数。
第三行输出要拦截所有导弹最少要配备这种导弹拦截系统的套数。
Sample Input
1
7
9 6 8 5 2 3 1
Sample Output
9 8 5 3 1
5
2
这是一个裸的最长上升子序列
#include <stdio.h>
#include <memory.h>
#define MAXV 60
int a[MAXV],dp[MAXV];
int main(){
int t,i,n,ma,flag,r,temp,j,tdis,k,tmin;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(i=1;i<=n;i++) {
scanf("%d",&a[i]);
dp[i]=1;
}
ma=-1;
for(i=n;i>=1;i--){
temp=0,flag=0;
for(j=n;j>i;j--)
if(a[i]>=a[j] && dp[i]<=dp[j]){
dp[i]=dp[j]+1;
}
if(dp[i]>ma) ma=dp[i]; //求最大拦截的个数
}
r=ma;tdis=1;tmin=30001; //选每个最长下降序列值的最大数输出
for(i=r;i>=1;i--){
temp=-1;
for(j=tdis;j<=n;j++)
if(dp[j]==r && a[j]>=temp && a[j]<=tmin){
temp=a[j];
k=j;
}
r--;
tmin=a[k];
tdis=k;
printf("%d ",a[k]);
}
for(i=1;i<=n;i++) dp[i]=1; //最少拦截导弹套数
for(i=n;i>=1;i--)
for(j=i+1;j<=n;j++)
if(a[j]>a[i] && dp[j]+1>dp[i])
dp[i]=dp[j]+1;
temp=-1;
for(i=1;i<=n;i++)
if(temp<dp[i])
temp=dp[i];
printf("\n%d\n%d\n",ma,temp);
}
return 0;
}