AcWing 1010. 拦截导弹(dp与贪心)

AcWing 1010. 拦截导弹(dp与贪心)_第1张图片

dp与贪心解LIS问题
1、dp + dp

O(n^2)
第一问显然每套导弹拦截系统拦截导弹高度为不升子序列,求最长的就好了
第二问求导弹拦截系统的个数可以转化为求最长上升子序列长度
证明见: Tian-Xing’s blog orz orz

1、首先我们把这些导弹分为s组(s即为所求答案)
可以看出每一组都是一个不升子序列
2、划分完后我们在组一里找一个原序列里以组一的开头点连续的不升子串的最后一个元素,可以知道在组2中一定有一个大与它的点
(如果组二中没有的话,那么组二中最高的导弹高度必然小于这个点,而其他的高度都小于这个高度而且是递减或相等的,那么没有必要再开一个组二了,矛盾,所以不存在找不到比他大的点的情况)
3、以此类推,对于每一个k组(1<=k 所以把这些点连起来,就是一条上升子序列。
4、设最长上升子序列长度为l
所求上升子序列为h
那么h<=l
因为最长上升子序列任意两个不在一组内
(如果在同一个组内,则每个组的数不成为一个不生子序列,矛盾)
所以l==h

作者:空空如也
链接:https://www.acwing.com/solution/content/10173/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

import java.io.*;
import java.lang.*;
import java.util.*;
class Main{
    static int[] a, f, g;
    static int n = 0, max1 = 0, max2 = 0;
    public static void main(String[] args)throws Exception{
        BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
        String[] params = buf.readLine().split(" ");
        n = params.length;
        a = new int[n + 1];
        for(int i = 1; i <= n; ++i){
            a[i] = Integer.valueOf(params[i - 1]);
        }
        f = new int[n + 1];
        g = new int[n + 1];
        for(int i = 1; i <= n; ++i){
            f[i] = 1;
            g[i] = 1;
            for(int j = 1; j < i; ++j){
                if(a[i] <= a[j])
                    f[i] = Math.max(f[i], f[j] + 1);
                if(a[i] > a[j])
                    g[i] = Math.max(g[i], g[j] + 1);
            }
            max1 = Math.max(max1, f[i]);
            max2 = Math.max(max2, g[i]);
        }
        
        System.out.println(max1);
        System.out.println(max2);
        
    }
}

 

你可能感兴趣的:(AcWing算法提高,动态规划,贪心算法)