【Acwing1010】拦截导弹(LIS+贪心)题解

题目描述

思路分析

本题有两问,第一问直接用lis的模板即可,下面重点看第二问

思路是贪心:

贪心流程:

从前往后扫描每一个数,对于每个数:

情况一:如果现有的子序列的结尾都小于当前的数,则创建子序列

情况二:将当前的数放到结尾大于等于它的最小的子序列后面

举个例子:

360 322 555 222.....

从左到右遍历上面序列,当遍历到222的时候,此时已经存在了两个子序列"360 322"和"555",两个子序列的结尾分别是322和555,其中322是大于等于222且是"322和555"中最小的数,所以把222放在序列"360 322"的后边!

贪心证明:

A表示贪心算法得到的序列个数,B表示最优解

B<=A 显然

如何证明B>=A?利用调整法:

如上图所示,假设a的后面是利用贪心算法插入的一个数,b的后面是最优解插入的一个数

在这两个序列后面补齐之后:

因为a是最优解的插法,所以b>=a

可以把x及后面的序列做交换,导致最优解变成了贪心解,并且总序列个数不变,所以B>=A

完整代码:

cpp 复制代码
#include<iostream>
#include<string>
#include<sstream>
using namespace std;
const int N=1010;
int f[N],h[N],q[N];
int cnt,res;
int n;
int main()
{
    string str;
    getline(cin,str);
    stringstream ssin(str);
    while(ssin>>q[n])n++;
    for(int i=0;i<n;i++)
    {
        f[i]=1;
        for(int j=0;j<i;j++)
        if(q[j]>=q[i])f[i]=max(f[j]+1,f[i]);
        res=max(res,f[i]);
        int k=0;
        while(k<cnt&&h[k]<q[i])k++;
        if(k<cnt)
        h[k]=q[i];
        else
        h[cnt++]=q[i];
    }
    cout<<res<<endl<<cnt<<endl;
    return 0;
}
相关推荐
ceclar123几秒前
C++范围操作(2)
开发语言·c++
一个不知名程序员www38 分钟前
算法学习入门---vector(C++)
c++·算法
云飞云共享云桌面1 小时前
无需配置传统电脑——智能装备工厂10个SolidWorks共享一台工作站
运维·服务器·前端·网络·算法·电脑
明洞日记1 小时前
【数据结构手册002】动态数组vector - 连续内存的艺术与科学
开发语言·数据结构·c++
福尔摩斯张1 小时前
《C 语言指针从入门到精通:全面笔记 + 实战习题深度解析》(超详细)
linux·运维·服务器·c语言·开发语言·c++·算法
橘颂TA1 小时前
【剑斩OFFER】算法的暴力美学——两整数之和
算法·leetcode·职场和发展
Dream it possible!2 小时前
LeetCode 面试经典 150_二叉搜索树_二叉搜索树的最小绝对差(85_530_C++_简单)
c++·leetcode·面试
xxxxxxllllllshi2 小时前
【LeetCode Hot100----14-贪心算法(01-05),包含多种方法,详细思路与代码,让你一篇文章看懂所有!】
java·数据结构·算法·leetcode·贪心算法
前端小L2 小时前
图论专题(二十二):并查集的“逻辑审判”——判断「等式方程的可满足性」
算法·矩阵·深度优先·图论·宽度优先
铁手飞鹰2 小时前
二叉树(C语言,手撕)
c语言·数据结构·算法·二叉树·深度优先·广度优先