【动态规划】拦截导弹_dilworth定理_最长递增子序列

问题 K: 【动态规划】拦截导弹

时间限制: 1 Sec  内存限制: 256 MB
提交: 39  解决: 10
[提交][状态][讨论版]

题目描述

张琪曼:“老师,修罗场是什么?”

墨老师:“修罗是佛家用语,修罗毕生以战斗为目标,修罗场指的是他们之间的死斗坑,人们通常用‘修罗场’来形容惨烈的战场。后来又引申出‘一个人在困境中做绝死奋斗’的意思。所以,这其实也在暗示我们,即使是身处绝境,也不要放弃奋斗。再说了,情况其实没有这么糟糕,因为我们最新的导弹拦截系统已经研制好了。”

魔法世界为了防御修罗王军团的导弹袭击,开发出一种导弹拦截系统──“要你命3000”。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到修罗王军团的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。

输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000 的正整数),计算这套系统最多能拦截多少导弹和如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

输入

一行,为导弹依次飞来的高度

输出

行,分别是最多能拦截的导弹数与要拦截所有导弹最少要配备的系统数

样例输入

389 207 155 300 299 170 158 65

样例输出

6
2

解题思路:题目所给的数据并不知道数量,所以添加一个字符,genchar()获取字符判断是不是空格,是空格说明后面还有数据,继续读入整数。  
    char cc;
    cin>>a[n++];
    while((cc=getchar())==‘ ‘){
        cin>>a[n++];
    }

  本来我是用的cc=getchar()!=‘\n’,结果提交oj,显示超时,程序根本停不下。所以不知道一行的最后用什么结束的,但改成只要不等于空格就结束,就可以了。 

  最多能拦截的导弹数很容易明白,就是求最长非递增子序列。

  最少要配备的系统数,刚开始我以为只要后面一个数比前面一个数大,然后c++,最后得到的就是要配备的系统数呢。

  但7 8 9 2 1 3 4 5这几个数就不可以,得到的是5,但结果应该是4。  5虽然比4大,但是他可以被打掉9的导弹打掉。所以5就不用再计入了。

  后来百度一下,应该是求最长递增子序列才行。

  然后证明这个好像是什么dilworth定理(最少链划分 = 最长反链长度)。

  这个还不太懂,一会再看看。

  还有个理解的方法,这个序列可以挑出很多递增子序列来,找一个不是最长的,再看他后面一定还有一个比这个序列中大的一个数,这个数也要用一个导弹。所以得找最长递增子序列才能打掉所有导弹。

代码:
#include <iostream>
#include <cstdio>

using namespace std;

int main()
{
    int n=0;
    int a[10000];
    int sum[10000];
    int sum2[10000];
    int c=0;//储存下一个高度比上一个高度大的情况数量
    int maxx;
    int maxx2;
    int ans=1;
    int ans2=1;
    char cc;
    cin>>a[n++];
    while((cc=getchar())==‘ ‘){
        cin>>a[n++];
    }
    sum[0]=1;
    sum2[0]=1;
    for(int i=1;i<n;i++){
        maxx=0;
        maxx2=0;
        for(int j=0;j<i;j++){
            if(a[j]>=a[i]){
                maxx=max(maxx,sum[j]);
            }
            if(a[j]<a[i]){
                maxx2=max(maxx2,sum2[j]);
            }
        }
        sum[i]=maxx+1;
        ans=max(ans,sum[i]);
        sum2[i]=maxx2+1;
        ans2=max(ans2,sum2[i]);
    }
    printf("%d\n%d",ans,ans2);
    return 0;
}
 
时间: 2024-12-19 05:08:08

【动态规划】拦截导弹_dilworth定理_最长递增子序列的相关文章

动态规划之最长递增子序列(LIS)

       在一个已知的序列{ a1,a2,--am}中,取出若干数组成新的序列{ ai1, ai2,-- aim},其中下标 i1,i2, --im保持递增,即新数列中的各个数之间依旧保持原数列中的先后顺序,那么称{ ai1, ai2,--aim}为原序列的一个子序列.若在子序列中,当下标 ix > iy时,aix > aiy,那么称其为原序列的一个递增子序列.最长递增子序列问题就是在一个给定的原序列中,求得其最长递增子序列的长度.       求最长递增子序列的递推公式为:      

【动态规划】【二分】【最长上升子序列】Vijos P1028 魔族密码

题目链接: https://vijos.org/p/1028 题目大意: 给N个字符串(N<=2000),求能组成词链的单词最多有几个. 如果在一个由一个词或多个词组成的表中,除了最后一个以外,每个单词都被其后的一个单词所包含 即前一个单词是后一个单词的前缀,则称词表为一个词链.例如下面单词组成了一个词链: i int integer 但下面的单词不组成词链: integer intern 题目思路: [动态规划][二分][最长上升子序列] 二分查找最长可达的长度. 1 // 2 //by co

动态规划之最长递增子序列

题目一:给定一个长度为N的数组,找出一个最长的单调递增子序列(不一定连续,但是顺序不能乱).并返回单调递增子序列的长度. 例如:给定一个长度为8的数组A{1,3,5,2,4,6,7,8},则其最长的单调递增子序列为{1,2,4,6,7,8},我们返回其长度6. 题目二:在题目一的基础上,我们要返回该子序列中的元素.例如,给定一个长度为8的数组A{1,3,5,2,4,6,7,8},我们返回的是单调递增子序列{1,2,4,6,7,8}. 解析:我们使用动态规划的思想来解决此问题,假设给定的数组为nu

动态规划之最长递增子序列问题详解

最近重新开始看动态规划,动态规划算法的有效性依赖于问题本身所具有的两个重要性质:最优子结构性质和子问题重叠性质. 1.最优子结构:当问题的最优解包含了其子问题的最优解时,称该问题具有最优子结构性质. 2.重叠子问题:在用递归算法自顶向下解问题时,每次产生的子问题并不总是新问题,有些子问题被反复计算多次.动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只解一次,而后将其解保存在一个表格中,在以后尽可能多地利用这些子问题的解. (二).动态规划算法的基本步骤设计一个标准的动态规划算法,通常

动态规划求解最长递增子序列的长度

一,问题描述 给定一个序列,求解它的最长 递增 子序列 的长度.比如: arr[] = {3,1,4,1,5,9,2,6,5}   的最长递增子序列长度为4.即为:1,4,5,9 二,算法分析 有两种方式来求解,一种是转化为LCS问题.即,首先对数组排序,将排序后的结果存储在辅助数组中.排序时间复杂度O(NlogN),排序后的数组与原数组组成了LCS(N,N)问题.解决LCS问题的时间复杂度为O(N^2),故整个算法的时间复杂度为O(N^2),空间复杂度为O(N) 另一种方式是直接用DP求解,算

尝试解释LIS(最长递增子序列)的一种动态规划算法

最长上升子序列就是求给定序列的最长的递增序列,其中不要求序列的元素在原序列中保持连续. 为了方便理解,可以举个例子: inta[] = {0,2,1,5,3,6,4,8,9,7}(数组下标从1开始)的一个最长的子序列1,3,4,7,9. 利用动态规划的思想,可以方便的求取这个解. 为了方便解释,我们定义dp(n)为长度为1至下标为n的最长子序列的长度(数组下标假设从1开始),{a[1],a[2],..,a[n]}为dp(n)对应的序列. 为了和程序对应,我采取自底向上的方式进行解释. 1.显然对

动态规划(DP),最长递增子序列(LIS)

题目链接:http://poj.org/problem?id=2533 解题报告: 状态转移方程: dp[i]表示以a[i]为结尾的LIS长度 状态转移方程: dp[0]=1; dp[i]=max(dp[k])+1,(k<i),(a[k]<a[i]) #include <stdio.h> #define MAX 1005 int a[MAX];///存数据 int dp[MAX];///dp[i]表示以a[i]为结尾的最长递增子序列(LIS)的长度 int main() { int

[算法]动态规划之最长递增子序列

最长递增子序列 #include<stdio.h> #include<stdlib.h> #include<time.h> #include<string.h> #define N 4 int solve(int *array, int n) { int *dp = (int *)malloc(n * sizeof(int)); int i; int j; int result; bzero((void *)dp, n * sizeof(int)); dp[

动态规划--最长递增子序列

经典的最长子序列问题,最近编程训练遇到此题苦无思路,在网上找到比较规范的解答,细思两天后还是觉得有点问题,现在整理总结如下: 参照 https://www.cnblogs.com/hapjin/p/5597658.html 1. 问题描述: 给定一个序列,求解它的最长 递增 子序列 的长度.比如: arr[] = {3,1,4,1,5,9,2,6,5}   的最长递增子序列长度为4.即为:1,4,5,9 2.DP算法分析: 按照上述作者的解答 ①最优子问题 设lis[i] 表示索引为 [0...