当前位置:首页 > 技术 > 正文内容

动态规划经典问题:最长上升子序列与导弹拦截

访客 技术 2026年6月30日 1

动态规划是算法学习中的核心内容,本文通过三个经典问题,逐步深入理解最长上升子序列(LIS)及其变体。

1. 基础LIS问题:B3637

给定一个序列,求出其中最长的严格递增子序列的长度。基本思路是定义dp[i]表示以第i个元素结尾的最长上升子序列长度,通过遍历前面所有元素,若a[j] < a[i],则更新dp[i] = max(dp[i], dp[j] + 1)

#include<iostream>
#include<algorithm>
using namespace std;
const int MAX = 1009;
long long arr[MAX], dp[MAX];

int main() {
    int n;
    cin >> n;
    for(int i = 0; i < n; i++) {
        cin >> arr[i];
        dp[i] = 1;
        for(int j = 0; j < i; j++) {
            if(arr[j] < arr[i]) {
                dp[i] = max(dp[i], dp[j] + 1);
            }
        }
    }
    long long ans = 0;
    for(int i = 0; i < n; i++) ans = max(ans, dp[i]);
    cout << ans << endl;
    return 0;
}

2. 老鼠体重与速度问题

给定老鼠的体重和速度数据,要求找出最大子集,使得体重严格递增且速度严格递减。处理方式是先对结构体排序:按体重升序,若体重相同则按速度降序。排序后,问题转化为在速度序列中找最长下降子序列,注意体重相等的情况不能计入。

#include<iostream>
#include<algorithm> 
const int SIZE = 100010;
using namespace std;
struct Mouse {
    int weight;
    int speed;
} mice[SIZE];
int dp[SIZE], n, total;

bool compare(Mouse x, Mouse y) {
    if(x.weight != y.weight) return x.weight < y.weight;
    return x.speed > y.speed;
}

int main() {
    cin >> n;
    for(int i = 0; i < n; i++) {
        cin >> mice[i].weight >> mice[i].speed;
    }
    sort(mice, mice + n, compare);
    
    for(int i = 0; i < n; i++) {
        dp[i] = 1;
        for(int j = 0; j < i; j++) {
            if(mice[i].speed < mice[j].speed && mice[i].weight != mice[j].weight) {
                dp[i] = max(dp[i], dp[j] + 1);
            }
        }
    }
    int result = 0;
    for(int i = 0; i < n; i++) result = max(result, dp[i]);
    cout << result << endl;
    return 0;
}

3. P1020 导弹拦截系统

问题描述:导弹拦截系统每次拦截的导弹高度不能高于前一次,给定导弹序列,求最多能拦截多少导弹(即最长不升子序列长度),以及全部拦截所需最少系统数。核心技巧:最少系统数等于最长上升子序列的长度(Dilworth定理)。因此问题简化为同时计算最长不升子序列和最长上升子序列。

#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 100010;
int heights[MAXN], dp_inc[MAXN], dp_dec[MAXN];

int main() {
    int idx = 0;
    while(scanf("%d", &heights[idx]) != EOF) {
        dp_inc[idx] = 1;
        dp_dec[idx] = 1;
        idx++;
    }
    for(int i = 0; i < idx; i++) {
        for(int j = 0; j < i; j++) {
            if(heights[i] > heights[j]) {
                dp_inc[i] = max(dp_inc[i], dp_inc[j] + 1);
            }
            if(heights[i] <= heights[j]) {
                dp_dec[i] = max(dp_dec[i], dp_dec[j] + 1);
            }
        }
    }
    int max_len = 0, min_sys = 0;
    for(int t = 0; t < idx; t++) {
        max_len = max(max_len, dp_dec[t]);
        min_sys = max(min_sys, dp_inc[t]);
    }
    cout << max_len << endl << min_sys << endl;
    return 0;
}

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。