目录
题目描述
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
提示
对于第一组数据,可以安排第 3 架飞机于 0 时刻开始降落,20 时刻完成降落。安排第 2 架飞机于 20 时刻开始降落,30 时刻完成降落。安排第 1 架飞机于 30 时刻开始降落,40 时刻完成降落。
对于第二组数据,无论如何安排,都会有飞机不能及时降落。
对于 30% 的数据,N ≤ 2。
对于 100% 的数据,1 ≤ T ≤ 10,1 ≤ N ≤ 10,0 ≤ Ti , Di , Li ≤ 105。
原题链接
C语言网:
题目 3151: 蓝桥杯2023年第十四届省赛真题-飞机降落
洛谷:
代码思路
代码一
代码一 C语言网和洛谷上都可以拿满分
代码一每行都写了代码备注,还十分详细 大家可以看看 思路很清晰
import java.util.Scanner;
public class Main {
static lx9_1 lx[];
static boolean bu[];
static int n;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int t = scanner.nextInt();
// 键盘录入t 利用循环输出每一组 看是YES还是NO
while (t-- > 0) {
n = scanner.nextInt();
// 建立一个类型为lx9_1的数组 长度为n
lx = new lx9_1[n];
// 判断lx[i]这个lx9_1类型的数组是否被使用过
bu = new boolean[n];
for (int i = 0; i < n; i++) {
int a = scanner.nextInt();
int b = scanner.nextInt();
int c = scanner.nextInt();
// 初始化lx[i]这个数组 并为之三个值存入一个对象 方便后续使用
lx[i] = new lx9_1(a, b, c);
}
// dfs有返回值 如果是true则是YES 是false则是NO
if (dfs(0, 0)) {
System.out.println("YES");
} else {
System.out.println("NO");
}
}
}
// 大法师 启动 目标:看一组飞机中 是否都可以安全降落 变量fj是飞机的降落的个数 变量last是某个飞机降落完成的最早时间(由贪心算法可知 降落早
// 可以使后面飞机有更多充足的时间降落) 先开始都为0
static boolean dfs(int fj, int last) {
// ## 飞机全部降落完了 然后就返回调用处(就是 $$ 这个的地方) 返回为true
if (fj == n) {
return true;
}
// 每次遍历所有lx数组 再由这 if (!bu[i] && lx[i].t + lx[i].d >= last) 看是否可以取
for (int i = 0; i < n; i++) {
// !bu[i] 是说要lx[i]这个数组没使用过 lx[i].t + lx[i].d >= last 这个是必要条件 只有这个的 (飞机来的时间 与
// 盘旋的时间的和) 大于 上一个飞机的最早降落完时间 才可以 降落 否则 出事故
if (!bu[i] && lx[i].t + lx[i].d >= last) {
// 进入了 那么 就将这个对像赋为true 让之后不再重复使用
bu[i] = true;
// $$ 要是都满足条件的化 改变fj和last的值 然后递归 直到 ## fj == n 返回true 然后就一直返回true
// 知道main方法里的dfs()收到ture
// 要是有false的化就要换一架飞机了
if (dfs(fj + 1, Math.max(last, lx[i].t) + lx[i].l)) {
return true;
}
// 将这个对像赋为false 可以让之后再出现
bu[i] = false;
}
}
// 1.当这一组都没合适的 就返回到main方法里的dfs()为false
// 2.在多次递归里面 的某一次没有符合条件的 需要这个退出这个方法 并返回false 让其重新换飞机
return false;
}
}
//创个类 达到三个值可以被一个对象存入的目的
class lx9_1 {
int t, d, l;
public lx9_1(int t, int d, int l) {
this.t = t;
this.d = d;
this.l = l;
}
}
代码二
这个代码 C语言网上可以拿满分,可洛谷上只能拿60分.代码复杂了些导致慢了,但思路却很清晰.
代码一 C语言网和洛谷上都可以拿满分 大家可以看看
原因:这个是蓝桥杯C语言组的题目,而Java的运行效率比普通语言慢3倍左右,还有C语言网上限时3秒,但洛谷上却是限时2秒.
代码二每行没写代码的备注,但 代码一 写了,还十分详细 大家可以看看
import java.util.Scanner;
public class Main {
static boolean bu[];
static lx7_1 lx1[];
static lx7_1 lx[];
static boolean bu1;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int t = scanner.nextInt();
while (t-- > 0) {
int n = scanner.nextInt();
lx = new lx7_1[n];
lx1 = new lx7_1[n];
bu = new boolean[n];
for (int i = 0; i < n; i++) {
int p = scanner.nextInt();
int l = scanner.nextInt();
int m = scanner.nextInt();
lx[i] = new lx7_1(p, l, m);
}
bu1 = false;
dfs(0, n);
if (bu1) {
System.out.println("YES");
} else {
System.out.println("NO");
}
}
}
static void dfs(int s, int t) {
if (bu1) {
return;
}
if (s == t) {
boolean bu2 = true;
int b = lx1[0].t + lx1[0].l;
for (int i = 1; i < t; i++) {
if (b > lx1[i].t + lx1[i].d) {
bu2 = false;
} else if (b <= lx1[i].t) {
b = lx1[i].t + lx1[i].l;
} else if (b >= lx1[i].t & b <= lx1[i].t + lx1[i].d) {
b = b + lx1[i].l;
}
}
if (bu2) {
bu1 = true;
}
}
for (int i = 0; i < t; i++) {
if (!bu[i]) {
bu[i] = true;
lx1[s] = lx[i];
dfs(s + 1, t);
bu[i] = false;
}
}
}
}
class lx7_1 {
int t;
int d;
int l;
public lx7_1(int t, int d, int l) {
this.t = t;
this.d = d;
this.l = l;
}
}