题目
有 架飞机准备降落到某个只有一条跑道的机场。
其中第 架飞机在 时刻到达机场上空,到达时它的剩余油料还可以继续盘旋 个单位时间,即它最早可以于 时刻开始降落,最晚可以于 时刻开始降落。
降落过程需要 个单位时间。
一架飞机降落完毕时,另一架飞机可以立即在同一时刻开始降落,但是不能在前一架飞机完成降落前开始降落。
请你判断 架飞机是否可以全部安全降落。
输入格式
输入包含多组数据。
第一行包含一个整数 ,代表测试数据的组数。
对于每组数据,第一行包含一个整数 。
以下 行,每行包含三个整数: , 和 。
输出格式
对于每组数据,输出 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
样例解释
对于第一组数据,可以安排第 架飞机于 时刻开始降落, 时刻完成降落。安排第 架飞机于 时刻开始降落, 时刻完成降落。安排第 架飞机于 时刻开始降落, 时刻完成降落。
对于第二组数据,无论如何安排,都会有飞机不能及时降落。
解题
方法一:DFS
思路
数据范围比较小,显然可以直接上暴搜(所有飞机的全排列)。
( 表示当前有多少架飞机已降落, 表示已经花费的时间):
- 出口:当 时,说明所有飞机都安全降落,把
suc
置为true
,退出程序。 - 枚举第 架飞机:
- 如果当前飞机( )还没有降落(
done[i] == false
):- 如果发现当前时间已经超过了该飞机的最晚起飞时刻(
t[i] + d[i] < tm
),说明这个飞机并不可能安全降落,直接退出递归(可行性剪枝); - 否则尝试降落该飞机(
done[i] = true
),递归下一架飞机( )(这里需要取 和 的最大值是因为不能让当前飞机的起飞时间早于其最早起飞时间); - 回溯(
done[i] = false
)。
- 如果发现当前时间已经超过了该飞机的最晚起飞时刻(
- 如果当前飞机( )还没有降落(
代码
#include <iostream>
#include <cstring>
using namespace std;
const int N = 20;
int m, n;
int t[N], d[N], l[N];
bool suc = false;
bool done[N];
void dfs(int u, int tm) {
if (u == n) {
suc = true;
return;
}
for (int i = 0; i < n; ++i) {
if (done[i]) continue;
if (t[i] + d[i] < tm) return;
done[i] = true;
dfs(u + 1, max(t[i], tm) + l[i]);
done[i] = false;
}
}
int main() {
int m;
scanf("%d", &m);
while (m--) {
scanf("%d", &n);
for (int i = 0; i < n; ++i) scanf("%d%d%d", &t[i], &d[i], &l[i]);
suc = false;
memset(done, false, sizeof(done));
dfs(0, 0);
puts(suc ? "YES" : "NO");
}
return 0;
}
评论区