関連トピック:
タイトル説明
ある国は敵国によるミサイル攻撃を防ぐためにミサイル迎撃システムを開発しました。
ただし、このミサイル迎撃システムには欠点があります。最初の砲弾はどのような高さにでも到達できますが、後続の各砲弾は前の砲弾より高くなることはできません。
ある日、レーダーが敵のミサイル攻撃を捕らえた。システムはまだ試用段階にあるため、システムが1つしかないため、すべてのミサイルを迎撃できない場合があります。
ミサイルの高度を順に入力し(レーダーによって提供される高度データは30,000以下の正の整数であり、ミサイルの数は1,000を超えません)、このシステムが迎撃できるミサイルの最大数と、すべてのミサイルを迎撃するために装備する必要があるミサイルのセット数を計算します。ミサイル迎撃システム。
入力フォーマット
続けて、ミサイルの高度を順に入力します。
出力フォーマット
1行目には、迎撃可能なミサイルの最大数を示す整数が含まれています。
2行目には、すべてのミサイルを迎撃するために装備するシステムの最小数を示す整数が含まれています。
入力サンプル:
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);
}
}