飞机降落——蓝桥编号3511

一、题目解析

        我写的可能有点乱,但是是一步步实现,中间可能会产生一些疑问,但整体应该是正确的。

       题目说了老长,实际上意思就是让我们分析一下,是否存在让所有的飞机降落成功的一个方案。

        但是有一个条件,那就是只有上一架飞机着陆之后,这一架飞机才能开始着陆。

        我们这里沿用一下贪心的思路,当上一架飞机落地之后,我当前的这个飞机马上开始着陆(但必须在可以开始着陆之后)。局部最优->全局最优,无明显反例,所以认为这个策略是正确的。

二、算法分析

        我们先从输入输出开始分析,首先我们要输入的是t次询问,每次询问都要输入n架飞机的各种状态,比如:飞机的可开始降落的时间,还能还能保持飞行的时间,以及降落所需要的时间。

       1.分析输入

        我们可以先写出以下的代码:

#include <iostream>

using namespace std;
int n,q;
const int N = 20;
int T[N],D[N],L[N];



int main()
{
  cin>>q;
  while(q--)
  {
    scanf("%d",&n);
    for(int i = 0;i<n;i++) scanf("%d%d%d",&T[i],&D[i],&L[i]);
    
  }

  return 0;
}

       2.确定使用的算法

        然后我们再来考虑,要用什么方法,目测本题的数据范围只有10,请看下边这个表——

        由表启发,我们不难想到可以使用dfs碰一下运气,万一可以呢?

       1)分析一下dfs的(部分)参数和返回值

        再看一下输出——问我们是否能够成功降落?输出YES或者NO 

        那么我们再写dfs的时候,直接让其返回真假即可(确定了dfs的返回值)。

        然后再来确定一下dfs函数的参数。

        在暴搜的时候,也就是暴力枚举每一个飞机,那我们肯定得知道自己枚举到哪一个飞机了,以及哪一个飞机被自己枚举过了。

        那我们不妨把我们当前枚举到得飞机的编号当作函数的参数(也就是他们的下标,我们从0开始)。而在一开始,所有的飞机都给他们一个状态,那就是未降落(flase),枚举的时候,如果他降落了,我们就把他的状态改为true,回溯的时候在改为false,这就是我们要开一个bool数组state的原因。

        于是我们结合一下输出和以上我们的分析,补充一下我们的代码。

#include <iostream>

using namespace std;
int n,q;
const int N = 20;
int T[N],D[N],L[N];
bool state[N];

bool dfs(int u)
{
  
}

int main()
{
  cin>>q;
  while(q--)
  {
    scanf("%d",&n);
    for(int i = 0;i<n;i++) scanf("%d%d%d",&T[i],&D[i],&L[i]);
    if(dfs(0))printf("YES\n");
    else printf("NO\n");
  }

  return 0;
}

       2)dfs函数的实现

        好,铺垫工作差不多结束了,现在进入我们的核心内容,dfs函数的编写。

        这里的dfs直接用朴素递归形式,分为一下三个步骤:

        1.递归的出口

        2.函数的主体

        3.函数的返回值

        Ⅰ.函数的出口

        这里我们有两种策略第一种就是把所有的飞机枚举完之后再去判断,第二种策略是在枚举的过程中,只枚举那些可能成功的方案(也就是用了剪枝的思想)

        这里我们选取的是第二章策略,因为他快。 

        我先直接给出递归的出口,等我们完成整个函数的主体之后,就会对这个递归出口有更深入的理解。

        

bool dfs(int u)
{
  if(u == n)//这里的n是一个全局变量,表示的是飞机的数量,但由于我们的飞机的编号是从0开始,
  {//所以当我们枚举到的飞机的编号等于飞机的数量的时候,绝对是已经全部枚举完了,并且这个方案一定是合理的
    return true;
  }
}

        相信读者可能会对这个递归出口产生一些质疑,但是请往下看。

Ⅱ.函数的主体

        我们用for循环去暴力枚举所有可能的情况——

bool dfs(int u)
{
  if(u == n)return true;

  for(int i = 0;i<n;i++)
  {
    if(!state[i])//表示这个位置的飞机还没有降落
    {
      
    }
  }
}

        但是我们发现了一个问题,那就是我们缺少条件,我们在题目解析的时候分析出,一架飞机落地的时候,一架飞机就要开始落地,这样的策略才是最优的。

        但是我们又怎么知道,上一架飞机的着陆时间的,所以我们分析出我们是缺少了参数

        我们把它设为time,表示上一架飞机的着陆时间。

        修改后的代码如下:

bool dfs(int u,int time)
{
  if(u == n)return true;

  for(int i = 0;i<n;i++)
  {
    if(!state[i]&&T[i]+D[i]>=time)//保证这个飞机还没有降落,并且它可以撑到这个time时候
    {
      state[i] = true;
      if(dfs(u+1,max(time,T[i])+L[i])) return true;//取最大的操作是因为可能上一架飞机已经着陆了,但是这一架飞机还不没到开始降落的世家。
      state[i] = false;
    }
  }
  return false;
}

        注释已经很详细了,这里不过多赘述。

Ⅲ.函数的返回值

        函数的返回值是真假,这个没有问题,继续沿用即可。 

三、最终代码呈现

        但是我们共用的同一个state数组,所以每一次使用前,都要将其用memset重置一下(头文件是<cstring>)。

#include <iostream>
#include <cstring>

using namespace std;
int n,q;
const int N = 20;
int T[N],D[N],L[N];
bool state[N];//表示这个飞机降落了没有

bool dfs(int u,int time)
{
  if(u == n)return true;

  for(int i = 0;i<n;i++)
  {
    if(!state[i]&&T[i]+D[i]>=time)//保证这个飞机还没有降落,并且它可以撑到这个time时候
    {
      state[i] = true;
      if(dfs(u+1,max(time,T[i])+L[i])) return true;
      state[i] = false;
    }
  }
  return false;
}
int main()
{
  // 请在此输入您的代码
  cin>>q;
  while(q--)
  {
    scanf("%d",&n);
    for(int i = 0;i<n;i++)scanf("%d%d%d",&T[i],&D[i],&L[i]);
    memset(state,0,sizeof state);//重置状态
    if(dfs(0,0))printf("YES\n");
    else printf("NO\n");
  }
  return 0;
}

  • 34
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值