导弹防御系统
传送门
这道题与 拦截导弹 类似,就是需要套一个爆搜,由于 \(n\) 很小,所以是不是用二分优化问题不大,这里是 \(O(n2^n)\),可以优化成 \(O(\log_2n2^n)\)。
#include<bits/stdc++.h>
using namespace std;
int ans,n,up[51],down[51],q[51];
void dfs(int u,int su,int sd){
if(su+sd>=ans)return;
if(u==n){
ans=su+sd;
return;
}
int k=0;
while(k<su&&up[k]>=q[u])++k;
int t=up[k];
up[k]=q[u];
if(k<su)dfs(u+1,su,sd);
else dfs(u+1,su+1,sd);
up[k]=t;
k=0;
while(k<sd&&down[k]<=q[u])++k;
t=down[k];
down[k]=q[u];
if(k<sd)dfs(u+1,su,sd);
else dfs(u+1,su,sd+1);
down[k]=t;
}
int main(){
while(cin>>n,n){
for(int i=0;i<n;++i)cin>>q[i];
ans=n;
dfs(0,0,0);
cout<<ans<<endl;
}
return 0;
}
y总的优化代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 60;
int down[N], up[N], q[N], n;
int res;
void dfs(int u, int su, int sd)
{
if (su + sd >= res) return;
if (u == n)
{
res = min(res, su + sd);
return;
}
int l = 0, r = su;
while (l < r)
{
int mid = l + r + 1 >> 1;
if (up[mid] >= q[u]) l = mid;
else r = mid - 1;
}
// 注意这里是<= su,因为这里up[]从下标1开始用,y总版本k < su是因为up[]从下标0开始用
if (r + 1 <= su)
{
int t = up[r + 1];
up[r + 1] = q[u];
dfs(u + 1, su, sd);
up[r + 1] = t;
}
else
{
up[r + 1] = q[u];
dfs(u + 1, su + 1, sd);
}
l = 0, r = sd;
while (l < r)
{
int mid = l + r + 1 >> 1;
if (down[mid] <= q[u]) l = mid;
else r = mid - 1;
}
if (r + 1 <= sd)
{
int t = down[r + 1];
down[r + 1] = q[u];
dfs(u + 1, su, sd);
down[r + 1] = t;
}
else
{
down[r + 1] = q[u];
dfs(u + 1, su, sd + 1);
}
}
int main()
{
up[0] = 2e9, down[0] = -2e9;
while (scanf("%d", &n), n)
{
for (int i = 0; i < n; i++) scanf("%d", &q[i]);
res = n;
dfs(0, 0, 0);
printf("%d\n", res);
}
return 0;
}