c++ · 洛谷P9241飞机降落 · 复盘

P9241 [蓝桥杯 2023 省 B] 飞机降落 - 洛谷

一:题目分析:

已知一组飞机的到达时间 t,可盘旋时间 d,降落所需时间 l,判断是否存在一组降落顺序,使得所有飞机都顺利降落,存在输出YES,否则输出NO;

二:思路:

数据结构部分:

1.设置结构体plane,存储每架飞机的三个信息;

2.设置两个数组a[N],b[N],前者按输入顺序存储要判断的这一组飞机信息,后者存储当前尝试的降落顺序;

3.设置bool数组vis[N],飞机降落过则true,反之是false;

4.设置bool变量f,用来判断是否已经找到一种方案,如果f=false,则说明还没有找到可执行的顺序;


DFS函数部分:

1.参数x:表示当前正在尝试安排第x架飞机;

2.该函数的作用:

                (1):能修改全局变量f,如果f=true,则找到了可执行的方案;

                (2):改变全局变量b,让其存储当前正在尝试的降落顺序;

                (3):修改全局变量vis数组,判断哪些飞机是降落过的;

3.结束条件:f==true,直接返回,每次安排完顺序之后,检查当前顺序是否可行;

4.递归:

        (1):遍历这一组所有飞机,选择为未降落的飞机,加入b数组中,并且标记;

        (2):递归调用dfs(x+1),尝试安排下一架函数,如果不符合条件,则回溯撤回,返回上一步方案,尝试其他的解;


主函数部分:

1.运用memset函数,把b数组的所有元素初始化为0,确保每次开始一组数据的测试的时候,b数组都是干净的;

附超多注释代码:

#include 
#define ll long long
using namespace std;
int n, t;
const int N = 11;
bool vis[N], f; // vis数组判断当前飞机是否已经降落过,true表示已经降落过,false表示还没有降落过
// f用来判断是否已经找到一种方案
// 当f为false的时候,表示还没有找到可行的降落顺序
struct plane
{
	int t, d, l;
} a[N], b[N];
// 这个写法等同于:
// plane a[N], b[N];
// a数组按顺序存储输入的飞机信息,是原始数据,不会被修改
// b数组是当前正在尝试的降落顺序,会随着dfs函数的递归调用而改变

// 这个dfs的作用:
// 1.能修改全局变量f,当f为true的时候,表示已经找到一种方案
// 2.能修改全局变量b,b数组存储当前正在尝试的降落顺序
// 3.能修改全局变量vis,vis数组判断哪些飞机是降落过的
void dfs(int x) // 递归函数,用于尝试所有可能的飞机降落顺序
// d表示当前正在尝试安排第d架飞机
{
	if (f) // 如果已经找到解,直接返回
		return;
	if (x > n) // 这时候安排完了所有的飞机,也就是生成了一种方案
	// 开始判断这个方案是否可行
	{
		int ls = b[1].t + b[1].l; // ls表示第一家飞机降落完毕的时间
		// 因为可以直接降落,不需要盘旋,所以不用加上b[1].d
		// ls在下面循环中的作用是记录当前飞机降落完毕的时间
		int fl = 1; // fl是一个标志位,用于表示当前顺序是否可行,
		// 0:不可行,1:可行
		for (int i = 2; i <= n; i++)
		{ // 从第二架飞机开始判断
			if (ls > b[i].t + b[i].d)
			{ // b[i].t + b[i].d表示当前飞机的最晚降落时间
				// 如果小于上一架飞机的降落完毕时间,则无法降落
				fl = 0;
				break;
			}
			// 如果前一架飞机的降落完成时间>当前飞机最早到达时间
			// 也就是说明当前飞机需要盘旋一段时间再降落
			else if (ls > b[i].t)
				ls += b[i].l;
			// 则前一架飞机降落完,现在飞机降落
			// 现在的飞机降落需要l,则ls += b[i].l;
			else
				// 这种情况是ls <= b[i].t
				//  也就是当前飞机可以直接降落,不需要盘旋
				ls = b[i].l + b[i].t;
		}
		if (fl == 1)
		{
			f = true; // 如果当前方案可行,则将f置为true,表示已经找到解
		}
	}
	for (int i = 1; i <= n; i++) // 遍历所有的飞机
		if (!vis[i])			 // 如果当前飞机还没有降落过
		{
			vis[i] = true; // 标记当前飞机已经降落
			b[x] = a[i];   // 将当前飞机的信息存入b数组,构造当前尝试的降落顺序
			dfs(x + 1);	   // 递归调用dfs函数,尝试下一架飞机
			// 如果当前方案不可行,会退回上一步,尝试其他方案
			vis[i] = false;
		}
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> t; // t组数据
	while (t--)
	{
		cin >> n; // n架飞机
		f = false;
		memset(b, 0, sizeof b);
		// 这个函数的意思是:将b数组中的所有元素都置为0;sizeof(b)表示b数组所占的字节数;
		for (int i = 1; i <= n; i++)
			cin >> a[i].t >> a[i].d >> a[i].l;
		dfs(1); // 从第一架飞机开始尝试降落
		if (f)
			cout << "YES\n";
		else
			cout << "NO\n";
	}
	return 0;
}

你可能感兴趣的:(c++,开发语言,算法,蓝桥杯,c语言,数据结构)