数据范围很小直接dfs全排列就行
有 N架飞机准备降落到某个只有一条跑道的机场。
其中第 i 架飞机在 Ti 时刻到达机场上空,到达时它的剩余油料还可以继续盘旋 Di 个单位时间,即它最早可以于 Ti 时刻开始降落,最晚可以于 Ti+Di 时刻开始降落。
降落过程需要 Li 个单位时间。
一架飞机降落完毕时,另一架飞机可以立即在同一时刻开始降落,但是不能在前一架飞机完成降落前开始降落。
请你判断 飞机是否可以全部安全降落。
输入格式
输入包含多组数据。
第一行包含一个整数 T,代表测试数据的组数。
对于每组数据,第一行包含一个整数 N。
以下 N 行,每行包含三个整数:Ti,Di 和 Li。
输出格式
对于每组数据,输出 YES 或者 NO,代表是否可以全部安全降落。
数据范围
对于 30% 的数据,N≤2
对于 100% 的数据,1≤T≤10,1≤N≤100≤Ti,Di,Li≤105
输入样例:
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 时刻完成降落。
对于第二组数据,无论如何安排,都会有飞机不能及时降落。
#include<iostream>
#include<cstring>
using namespace std;
const int N=20;
int t,n;
struct Plane{
int t,d,l;
};
int tim[N];
Plane a[N];
bool st[15],flag;//st记录是否已经降落,flag标记是否降落完成
void dfs(int k,int last)//k表示已经降落的飞机数量,last表示上一架飞机降落完成的时间
{
if(k>=n)//已经全部降落
{
puts("YES");
flag=true;
}
if(flag) return;//已经完成就不再搜索
for(int i=1;i<=n;i++)//枚举每一种情况
{
if(!st[i])//还没降落
{
if(tim[i]<last) return;//如果最迟降落时间已经过去就不满足,剪掉
st[i]=true;
if(last<a[i].t) dfs(k+1,a[i].t+a[i].l);//降落时间小于当前飞机的最早降落时间
//直接用最早的降落时间+降落所需要的时间
else dfs(k+1,last+a[i].l);//立马降落
st[i]=false;//还原现场
}
}
}
int main()
{
cin>>t;
while(t--)
{
cin>>n;
memset(st,0,sizeof st);//设置为都未降落
flag=false;//还没完成
for(int i=1;i<=n;i++)
{
cin>>a[i].t>>a[i].d>>a[i].l;
tim[i]=a[i].t+a[i].d; // 计算最迟降落时间
}
dfs(0,0);
if(!flag) puts("NO");//所有的情况都不满足
}
return 0;
}
如果不理解递归过程可以先看这个
把 1∼n 这 n 个整数排成一行后随机打乱顺序,输出所有可能的次序。
输入格式
一个整数 n。
输出格式
按照从小到大的顺序输出所有方案,每行 1个。
首先,同一行相邻两个数用一个空格隔开。
其次,对于两个不同的行,对应下标的数一一比较,字典序较小的排在前面。
数据范围
1≤n≤9
输入样例:
3
输出样例:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
#include<iostream>
using namespace std;
const int N = 10;
int path[N];//保存序列
int state[N];//数字是否被用过
int n;
void dfs(int u)
{
if(u > n)//递归结束条件
{
for(int i = 1; i <= n; i++)//输出方案
cout << path[i] << " ";
cout << endl;
}
for(int i = 1; i <= n; i++)//空位上可以选择的数字为:1 ~ n
{
if(!state[i])//如果数字 i 没有被用过
{
path[u] = i;//放入空位
state[i] = 1;//数字被用,修改状态
dfs(u + 1);//填下一个位
state[i] = 0;//回溯,取出 i
}
}
}
int main()
{
cin >> n;
dfs(1);
return 0;
}