2023蓝桥杯大赛B组C语言-试题D:飞机降落

题目:

N 架飞机准备降落到某个只有一条跑道的机场。其中第 i 架飞机在 Ti 时刻到达机场上空,到达时它的剩余油料还可以继续盘旋 Di 个单位时间,即它最早

可以于 Ti 时刻开始降落,最晚可以于 Ti + Di 时刻开始降落。降落过程需要 Li个单位时间。

一架飞机降落完毕时,另一架飞机可以立即在同一时刻开始降落,但是不能在前一架飞机完成降落前开始降落。

请你判断 N 架飞机是否可以全部安全降落。

输入格式
输入包含多组数据。

第一行包含一个整数 T,代表测试数据的组数。

对于每组数据,第一行包含一个整数 N。

以下 N 行,每行包含三个整数:Ti,Di 和 Li。

输出格式
对于每组数据,输出 YES 或者 NO,代表是否可以全部安全降落。

样例输入
复制

2
3
0 100 10
10 10 10
0 2 20
3
0 10 20
10 10 20
20 10 20
样例输出
复制

YES
NO

解题步骤:

这道题的重点显然难点不在“多个案例”这个点上,所以我们可以先解决一个情况,那么这个题目就可以先变成:

第一行包含一个整数 N,代表测试的飞机数目。

以下 N 行,每行包含三个整数:Ti,Di 和 Li。

然后直接判断这N个飞机能否安全降落就行了

对于飞机,因为其含有三个变量,所以我们不妨直接将飞机声明为结构体的形式(本人习惯用class了,所以这里的代码也是class)

class plane
{
	public:
		int reach;
		int insist;  //英文水平不好,这应该是坚持的意思吧
		int land;
		int end()  
		{
			return reach+insist;
		}
};

飞机的四个成员分别是:到达时间,盘旋时间,降落所需时间,必须降落时间

接着,我们考虑,当这些飞机被声明之后,我们要如何确定存在安全降落的方案呢?

显然,如果对于一个具体的方案(飞机顺序确定),我们是很容易判断出它是不是安全方案的:

int timeline;
bool safe(plane *p,int n)
{
	timeline=0;          //刷新时间线
	for(int i=0;i<n;i++)
	{
		if(p[i].end()<timeline) return false;
		else timeline+=p[i].land;
	}
	return true;
}

那么,如果我们可以穷举出所有的方案,然后再通过上面的函数判读这些方案里面有没有安全的方案,就可以判断出这次降落是否安全了

因此:对于简化的问题,可以得到以下代码

#include <bits/stdc++.h>
using namespace std;
int timeline;        //时间线 
int safe_case;       //统计安全方案 
class plane
{
	public:
		int reach;
		int insist;
		int land;
		int end()  
		{
			return reach+insist;
		}
};
bool safe(plane *p,int n)
{
	timeline=0;
	for(int i=0;i<n;i++)
	{
		if(p[i].end()<timeline) return false;
		else timeline+=p[i].land;
	}
	safe_case++;   //安全方案出现,进行统计 
	return true;
}
void all_case(plane *p,int n,int len)//递归得出全排列并进行判断 
{
	if(n==1) 
	{
		safe(p,len);
	}
	else
	{
		for(int i=0;i<n;i++)
		{
			swap(p[i],p[n-1]);
			all_case(p,n-1,len);
			swap(p[i],p[n-1]);
		}
	}
}
int main()
{
	safe_case=0;
	int n;
	cin>>n;
	plane *p=new plane [n];
	for(int i=0;i<n;i++)
	{
		cin>>p[i].reach>>p[i].insist>>p[i].land;
	}
	all_case(p,n,n);
	if(safe_case) cout<<"Yes"<<endl;
	else cout<<"No"<<endl;
	delete []p;
	return 0;
}

最难的一点解决了,接下来原题的答案就呼之欲出了

#include <bits/stdc++.h>
using namespace std;
int timeline;        //时间线 
int safe_case;       //统计安全方案 
class plane
{
	public:
		int reach;
		int insist;
		int land;
		int end()  
		{
			return reach+insist;
		}
};
bool safe(plane *p,int n)
{
	timeline=0;
	for(int i=0;i<n;i++)
	{
		if(p[i].end()<timeline) return false;
		else timeline+=p[i].land;
	}
	safe_case++;   //安全方案出现,进行统计 
	return true;
}
void all_case(plane *p,int n,int len)//递归得出全排列并进行判断 
{
	if(n==1) 
	{
		safe(p,len);
	}
	else
	{
		for(int i=0;i<n;i++)
		{
			swap(p[i],p[n-1]);
			all_case(p,n-1,len);
			swap(p[i],p[n-1]);
		}
	}
}
int main()
{
	int num;
	cin>>num;
	for(int i=0;i<num;i++)
	{
	    safe_case=0;//每次降落都进行安全方案的刷新 
	    int n;
	    cin>>n;
	    plane *p=new plane [n];
	    for(int i=0;i<n;i++)
	    {
		    cin>>p[i].reach>>p[i].insist>>p[i].land;
	    }
	    all_case(p,n,n);
	    if(safe_case) cout<<"Yes"<<endl;
	    else cout<<"No"<<endl;
	    delete []p;
    }
	return 0;
}

结语:本人属大一新生,并且算法部分属于野路子,部分的算法甚至是名词可能会有偏误(包括那个全排列算法也是野路子,不标准),还望海涵,期待大佬的批评指正

  • 17
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值