导弹防御系统

发布时间 2023-05-20 08:09:03作者: wscqwq

传送门

这道题与 拦截导弹 类似,就是需要套一个爆搜,由于 \(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;
}