1187. 导弹防御系统
为了对抗附近恶意国家的威胁,R国更新了他们的导弹防御系统。
一套防御系统的导弹拦截高度要么一直 严格单调 上升要么一直 严格单调 下降。
例如,一套系统先后拦截了高度为 3 和高度为 4 的两发导弹,那么接下来该系统就只能拦截高度大于 4 的导弹。
给定即将袭来的一系列导弹的高度,请你求出至少需要多少套防御系统,就可以将它们全部击落。
输入格式
输入包含多组测试用例。
对于每个测试用例,第一行包含整数 n,表示来袭导弹数量。
第二行包含 n 个不同的整数,表示每个导弹的高度。
当输入测试用例 n=0 时,表示输入终止,且该用例无需处理。
输出格式
对于每个测试用例,输出一个占据一行的整数,表示所需的防御系统数量。
数据范围
1≤n≤50
输入样例:
5
3 5 2 4 1
0
输出样例:
2
样例解释
对于给出样例,最少需要两套防御系统。
一套击落高度为 3,4 的导弹,另一套击落高度为 5,2,1的导弹。
题解
由于题目给了两种选择,每个数即可加入单调上升的序列,也可以加入单调下降的序列,且我们无法得知哪一种方案更好,因此需要枚举所有状态。
所以,本题不适用动态规划。
整体思路是,枚举每个数加入的序列种类,但是这样的复杂度是2的n次方,指数级复杂度,可以用最优化剪枝优化。
举个例子,如果将一个数加入了上升序列,那么最优的放法,就是放入允许的最大的末尾序列元素后面,这样可以使后面的队列元素不会有更差的放法;
用数学语言描述就是,对于所有的上升序列尾部元素集合{up},当元素 x>up[i]且x<=up[i+1]时,使up[i]=x;
然后在dfs过程中,如果当前结果已经大于等于目前的最优解,可以直接ruturn剪掉这一部分。(参考了他人的思路和代码)
代码
#include <bits/stdc++.h>
#define ll long long
#define PII pair<int,int>
using namespace std;
int n,ans=50;
int a[100],up[100],down[100];
void dfs(int x,int u,int d)
{
if(u+d>=ans) return;
if(x==n+1){
ans=min(ans,u+d);
return;
}
int k = 0;
while (k < u && up[k] >= a[x]) k++;
int num = up[k];
up[k] = a[x];
if (k < u) dfs(x + 1, u, d);
else dfs(x + 1, u + 1, d);
up[k] = num;
k = 0;
while (k < d && down[k] <= a[x]) k++;
num = down[k];
down[k] = a[x];
if (k < d) dfs(x + 1, u, d);
else dfs(x + 1, u , d + 1);
down[k] = num;
}
void solve()
{
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
ans=50;
dfs(1,0,0);
cout<<ans<<endl;
}
int main()
{
int T=1;
//cin>>T;
while(1)
{
cin>>n;
if(n==0) break;
else solve();
}
return 0;
}
分类:
ACM训练题解 / acwing
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】