【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;
}
相关推荐
mit6.824几秒前
437贪心
算法
hetao1733837几秒前
2026-01-19~20 hetao1733837 的刷题笔记
c++·笔记·算法
梓䈑5 分钟前
【Linux系统】实现线程池项目(含日志类的设计)
linux·服务器·c++
秋刀鱼程序编程21 分钟前
Java编程基础入门(四)---选择循环语句
java·开发语言·算法
优雅的潮叭23 分钟前
c++ 学习笔记之 volatile与atomic
c++·笔记·学习
wen__xvn24 分钟前
基础算法集训第04天:选择排序和冒泡排序
数据结构·算法·leetcode
充值修改昵称31 分钟前
数据结构基础:二叉树高效数据结构的奥秘
数据结构·python·算法
Zsy_0510031 小时前
【C++】类和对象(二)
开发语言·c++
啊阿狸不会拉杆1 小时前
《机器学习》第四章-无监督学习
人工智能·学习·算法·机器学习·计算机视觉
Java程序员威哥1 小时前
用Java玩转机器学习:协同过滤算法实战(比Python快3倍的工程实现)
java·开发语言·后端·python·算法·spring·机器学习