luogu P10490 Missile Defence System 题解
P10490 Missile Defence System
题目描述
为了对抗附近恶意国家的威胁,R 国更新了他们的导弹防御系统。
一套防御系统的导弹拦截高度要么一直严格单调上升要么一直严格单调下降。
例如,一套系统先后拦截了高度为 \(3\) 和高度为 \(4\) 的两发导弹,那么接下来该系统就只能拦截高度大于 \(4\) 的导弹。
给定即将袭来的一系列导弹的高度,请你求出至少需要多少套防御系统,就可以将它们全部击落。
输入格式
输入包含多组测试用例。
对于每个测试用例,第一行包含整数 \(n\),表示来袭导弹数量。
第二行包含 \(n\) 个不同的整数,表示每个导弹的高度。
当输入测试用例 \(n=0\) 时,表示输入终止,且该用例无需处理。
输出格式
对于每个测试用例,输出一行,一个整数,表示所需的防御系统数量。
输入输出样例 #1
输入 #1
5
3 5 2 4 1
0
输出 #1
2
说明/提示
样例解释
对于样例,需要两套系统。一套击落高度为 \(3,4\) 的导弹,另一套击落高度为 \(5,2,1\) 的导弹。
数据规模与约定
\(1 \leq n \leq 50\)。
思路概述
(题面让我想起了“拦截导弹”这道老题……)
对于每一个导弹,它有两种可能性:
-
接在上升序列上。
-
接在下降序列上。
此时,我们可以贪心:每个导弹都选择“当前离自己最近的”序列。这样能尽最大可能地保存每个序列的“潜力值”。
代码概述
#include<bits/stdc++.h>
using namespace std;
const int N=60;
int n,ans,a[N];
vector<int> up,down;
void dfs(int now) {
int us=up.size();
int ds=down.size();
if(us+ds>=ans) return;
if(now>n){
ans=min(ans,us+ds);
return ;
}
for(int i=0;i<us;i++)
if(up[i]<a[now]) {
int t=up[i]; up[i]=a[now];
dfs(now+1);
up[i]=t;
break;
}
if(us==0 || up[us-1]>=a[now]) {
up.push_back(a[now]);
dfs(now+1);
up.pop_back();
}
for(int i=0;i<ds;i++){
if(down[i]>a[now]){
int t=down[i];
down[i]=a[now];
dfs(now+1);
down[i]=t;
break;
}
}
if(ds==0 || down[ds-1]<=a[now]){
down.push_back(a[now]);
dfs(now+1);
down.pop_back();
}
return;
}
int main(){
while(scanf("%d",&n)){
if(n==0) break;
up.clear(); down.clear();
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
ans=0x3f3f3f3f;
dfs(1);
printf("%d\n",ans);
}
return 0;
}

浙公网安备 33010602011771号