[蓝桥杯]飞机降落
·
题意
n架飞机要降落 每架飞机能在[t[i],t[i]+d[i]]的时刻区间内降落 降落需要l[i]的时间
一架飞机降落完毕时,另一架飞机可以立即在同一时刻开始降落,但是不能在前一架飞机完成降落前开始降落
判断这些飞机能否全部降落
1≤𝑇≤10,1≤𝑁≤10,0≤𝑇𝑖,𝐷𝑖,𝐿𝑖≤105。
方法一 全排列
思路:
数据很小
枚举降落顺序 直接用next_permutation
每个飞机有一个可降落时刻的区间[t[i],t[i]+d[i]] 降落耗时l[i]
维护now变量 记录上一架飞机降落结束的时间 当前飞机能在now之后开始降落
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int,int>
#define ar2 array<int,2>
#define ar3 array<int,3>
#define ar4 array<int,4>
#define endl '\n'
void cmax(int &a,int b){a=max(a,b);}
void cmin(int &a,int b){a=min(a,b);}
const int N=20,MOD=1e9+7,INF=0x3f3f3f3f,LINF=LLONG_MAX;
int t[N],d[N],l[N],n;
pii p[N];
int per[N];
/*
枚举降落顺序
每个飞机有一个可降落时刻的区间[t[i],t[i]+d[i]] 降落耗时l[i]
维护now变量记录当前能在now之后开始降落
*/
bool check(){
int now=0;
for(int i=1;i<=n;i++){
int idx=per[i];
if(now>p[idx].second) return 0;
if(now<=p[idx].first) {
now=p[idx].first;
}
now+=l[idx];
}
return 1;
}
void solve() {
cin>>n;
for(int i=1;i<=n;i++) cin>>t[i]>>d[i]>>l[i];
for(int i=1;i<=n;i++){
p[i]={t[i],t[i]+d[i]};
}
for(int i=1;i<=n;i++) per[i]=i;
do
{
if(check()){
cout<<"YES"<<endl;
return;
}
} while (next_permutation(p+1,p+1+n));
cout<<"NO"<<endl;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int t=1;
cin>>t;
while (t--) solve();
}
方法二 DFS
思路:
来自 [蓝桥杯]真题讲解:飞机降落(DFS枚举)_蓝桥杯飞机降落-CSDN博客
开一个状态数组 记录当前这架飞机有没有降落过
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int,int>
#define ar2 array<int,2>
#define ar3 array<int,3>
#define ar4 array<int,4>
#define endl '\n'
void cmax(int &a,int b){a=max(a,b);}
void cmin(int &a,int b){a=min(a,b);}
const int N=20,MOD=1e9+7,INF=0x3f3f3f3f,LINF=LLONG_MAX;
int t[N],d[N],l[N],n;
pii p[N];
bool st[N];
bool dfs(int idx,int now){//idx表示当前有idx个飞机成功降落 now表示上一架飞机降落结束的时刻
if(idx>=n) return 1;
for(int i=1;i<=n;i++){
if(st[i]) continue;
auto [ll,rr]=p[i];
if(now>rr) {
return 0;//now只会变大 所以这个飞机一定降落不了 直接return 0
}
//这个飞机能降落 先标记为1
st[i]=1;
int t=max(ll,now)+l[i];
if(dfs(idx+1,t)) return 1;//宏观地看 如果后面所有的飞机都成功降落 就返回1
//这个方案不成功 所以在这一步撤销选择 把st[i]重置为0
st[i]=0;
}
return 0;
}
void solve() {
cin>>n;
for(int i=1;i<=n;i++) cin>>t[i]>>d[i]>>l[i];
for(int i=1;i<=n;i++){
p[i]={t[i],t[i]+d[i]};
}
memset(st,0,sizeof st);
if(dfs(0,0)){
cout<<"YES"<<endl;
}else{
cout<<"NO"<<endl;
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int t=1;
cin>>t;
while (t--) solve();
}
具体看注释
关于now>rr时return 0:
return 0就是剪枝了 其实continue也可以 但是速度慢一些
可以证明 now只会变大 当前now都比rr大了 往后递归now永远比rr大 所以这架飞机一定没法降落 所以这种方案直接return 0就行了
另外多组数据 记得初始化st数组
更多推荐



所有评论(0)