AcWing 187. 导弹防御系统

AcWing 187. 导弹防御系统

为了对抗附近恶意国家的威胁,R 国更新了他们的导弹防御系统。

一套防御系统的导弹拦截高度要么一直 严格单调 上升要么一直 严格单调 下降。

例如,一套系统先后拦截了高度为 3 和高度为 4 的两发导弹,那么接下来该系统就只能拦截高度大于 4 的导弹。

给定即将袭来的一系列导弹的高度,请你求出至少需要多少套防御系统,就可以将它们全部击落。

输入格式
输入包含多组测试用例。

对于每个测试用例,第一行包含整数 n,表示来袭导弹数量。

第二行包含 n 个不同的整数,表示每个导弹的高度。

当输入测试用例 n=0 时,表示输入终止,且该用例无需处理。

输出格式
对于每个测试用例,输出一个占据一行的整数,表示所需的防御系统数量。

数据范围
1≤n≤50
输入样例:
5
3 5 2 4 1
0
输出样例:
2
样例解释
对于给出样例,最少需要两套防御系统。

一套击落高度为 3,4 的导弹,另一套击落高度为 5,2,1 的导弹。

这道题的题意是求覆盖最长上升子序列和最长下降子序列的个数。

我们单个求最长上升子序列有一个固定的模板。

     for(int i=0;i<n;i++)
     {
         int k=0;
         while(k<cnt&&t[k]<p[i]) k++;
         t[k]=p[i];
         if(k>=cnt)
         cnt++;
     }

要是想求覆盖二者的最小区间数,目前y总说没有想到很好的办法,然后他用了爆搜的方法去做,我们首先一一枚举,我们先分开枚举是放到上升子序列还是放到下降子序列,所以我们先枚举上升,在枚举下降,最后我们可以得出结论,因为递归的特性,所以我们可以枚举2n的所有可能,然后需要注意的地方是,我第一次写爆搜代码的时候,我仔细的检查了一遍我的第一次代码。

#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

const int N=55;

int q[N],up[N],down[N];
int ans;
int n;

void dfs(int u,int su,int sd)
{
    if(su+sd>ans)
    return ;
    if(u==n)
    {
        ans=min(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(void)
{
    while(cin>>n,n)
    {
        for(int i=0;i<n;i++) cin>>q[i];
        ans=n;
        dfs(0,0,0);
        cout<<ans<<endl;
    }
}

这个是错误代码,我TLE了,我刚开始也是debug了很多次,
最后败在了一个小细节,当我们dfs的时候,尽可能多的去剪枝,减少条件。

我在

    if(su+sd>=ans)
    return;

这个条件上少加了一个等号,我以为没什么,仔细想了想会增加计算量,这个能去就去。
dfs本身就是时间复杂度很大的算法,所以我们要想办法去除。
最终代码如下:

#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

const int N=55;

int q[N],up[N],down[N];
int ans;
int n;

void dfs(int u,int su,int sd)
{
    if(su+sd>=ans)
    return;
    if(u==n)
    {
        ans=min(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(void)
{
    while(cin>>n,n)
    {
        for(int i=0;i<n;i++) cin>>q[i];
        ans=n;
        dfs(0,0,0);
        cout<<ans<<endl;
    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好!对于导弹制导系统的仿真,MATLAB是一个非常强大和常用的工具。您可以使用MATLAB来建立导弹的数学模型,并进行仿真以评估其性能。 下面是一些可能有助于您进行导弹制导系统仿真的步骤和工具: 1. 建立导弹模型:使用MATLAB中的数学和物理建模工具,您可以建立导弹的运动方程和环境模型。这可能涉及到姿态控制、飞行动力学、弹道轨迹等方面的模拟。 2. 设计制导算法:根据您的需求和制导系统的特点,设计适当的制导算法。这可能包括比例导航、最优控制、滑模控制等。MATLAB提供了丰富的控制设计工具和函数,可以帮助您进行算法设计和评估。 3. 仿真导弹系统:使用MATLAB中的仿真工具,如Simulink,您可以将导弹模型和制导算法集成在一起,并进行系统级的仿真。这将使您能够评估导弹在不同条件下的性能,并进行性能分析和优化。 4. 分析和结果可视化:MATLAB提供了强大的数据分析和可视化工具,您可以使用这些工具来分析导弹仿真的结果。这可以包括导弹的轨迹、姿态、速度等方面的数据分析,以及性能指标的评估和比较。 总之,MATLAB是一个非常适合进行导弹制导系统仿真的工具,它提供了丰富的数学建模、控制设计和仿真分析功能。希望这些信息能对您有所帮助!如果您有任何其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值