相关题目:
题目描述
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。
但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。
某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数,导弹数不超过1000),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入格式
共一行,输入导弹依次飞来的高度。
输出格式
第一行包含一个整数,表示最多能拦截的导弹数。
第二行包含一个整数,表示要拦截所有导弹最少要配备的系统数。
输入样例:
389 207 155 300 299 170 158 65
输出样例:
6
2
思路:
1.第一问很简单就是求最长下降子序列;
2.第二问乍一看没想出来,按照不会就模拟的想法我们可以举几个例子来
看看规律,来猜做法;
例1.207 155; 207<155可以构成一个下降子序列,因此只需要一台机器;
例2.207 155 300;207<155可以构成一个下降子序列,但300>207,无法同一
一个降序列中,因此需要两个;
例3.155 300 311 299 170;155<300,300<311,因此155无法加入以300
为开头的下降子序列中,300无法加入以311位首的下降子序列中;
我们可以由此发现每段上升子序列中的每个导弹都单独需要一个机器来拦截,
例1没有上升子序列,只有一个下降子序列,需要一台;
例2上升子序列中有两个导弹,其中一个导弹正好是下降子序列的头;
例3上升子序列中有三个导弹,其中一个导弹是下降子序列的头;
我们这样就大概猜答案用最长上升子序列来做,事实证明这种做法在洛谷里
会只有100分,若想200分用树状数组这个写不来,哈哈哈哈~,还有就是
我这个做法是是有一个定理的叫Dilworth定理,感兴趣的可以上网查一下;
代码
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
String [] arr2=input.nextLine().split(" ");
int N=arr2.length;
int []dp=new int[N+1];
int []dp2=new int[N+1];
int []arr=new int[N+1];
int index=0;
for(int i=1;i<=N;i++){
arr[i]=Integer.parseInt(arr2[i-1]);
}
int max=0;
for(int i=1;i<=N;i++){
dp[i]=1;
for(int j=1;j<i;j++){
if(arr[i]<=arr[j])
dp[i]=Math.max(dp[i],dp[j]+1);
max=Math.max(dp[i],max);
}
}
// 在一个序列中,划分成最少的最长不上升子序列的数量等于这个序列的最长上升子序列的长度
//所以,我们只要求这个序列最长上升子序列的长度,思路跟第一题差不多,只不过,条件要换成h[i]>h[j]。
int max2=0;
for(int i=1;i<=N;i++){
dp2[i]=1;
for(int j=1;j<i;j++){
if(arr[i]>arr[j])
dp2[i]=Math.max(dp2[i],dp2[j]+1);
max2=Math.max(dp2[i],max2);
}
}
System.out.println(max);
System.out.println(max2);
}
}