NC16810 [NOIP1999]拦截导弹
题目
题目描述
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入描述
1行,若干个整数(个数≤100000)
输出描述
2行,每行一个整数,第一个数字表示这套系统最多能拦截多少导弹,第二个数字表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
示例1
输入
389 207 155 300 299 170 158 65
输出
6 2
题解
知识点:线性dp。
第一问没什么好说的,一个最长不上升子序列。
第二问用到dilworth定理:最长上升子序列的划分数 = 最长不上升子序列的长度。手玩理解一下就好,具体证明可以百度qwq。
这里要求最长不上升子序列的划分数,也就是求LCS的长度。
时间复杂度
空间复杂度
代码
#include <bits/stdc++.h> using namespace std; int a[100007], dp[100007]; int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int n = 0; while (cin >> a[n++]); n--; for (int i = 0;i < n;i++) { dp[i] = 1; for (int j = 0;j < i;j++) if (a[i] <= a[j]) dp[i] = max(dp[i], dp[j] + 1); } int ans = 0; for (int i = 0;i < n;i++) ans = max(ans, dp[i]); cout << ans << '\n'; for (int i = 0;i < n;i++) { dp[i] = 1; for (int j = 0;j < i;j++) if (a[i] > a[j]) dp[i] = max(dp[i], dp[j] + 1); } ans = 0; for (int i = 0;i < n;i++) ans = max(ans, dp[i]); cout << ans << '\n'; return 0; }
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/16577982.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!