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