有 N 架飞机准备降落到某个只有一条跑道的机场。
其中第 i架飞机在 Ti 时刻到达机场上空,到达时它的剩余油料还可以继续盘旋 Di个单位时间,即它最早可以于 Ti 时刻开始降落,最晚可以于 Ti+Di 时刻开始降落。
降落过程需要 Li 个单位时间。
一架飞机降落完毕时,另一架飞机可以立即在同一时刻开始降落,但是不能在前一架飞机完成降落前开始降落。
请你判断 N 架飞机是否可以全部安全降落。
输入包含多组数据。
第一行包含一个整数 T,代表测试数据的组数。
对于每组数据,第一行包含一个整数 N。
以下 N行,每行包含三个整数:Ti,Di 和 Li。
输出格式
对于每组数据,输出 YES
或者 NO
,代表是否可以全部安全降落。
数据范围
对于 30%30% 的数据,N≤2。
对于 100%100% 的数据,1≤T≤10,1≤N≤10,0≤Ti,Di,Li≤10^5。
本题代码
#include
#include
#include
using namespace std;
const int N = 1e5+10;
bool st[N];
struct plane
{
int t,d,l;
}p[N];
int n;
bool dfs(int u,int last)
{
if(u==n)return true;
for (int i = 0; i < n; i ++ )
{
int t,d,l;
t=p[i].t,d=p[i].d,l=p[i].l;
if(!st[i]&&last<=d+t)
{
st[i]=true;
if(dfs(u+1,max(last,t)+l))return true;
st[i]=false;
}
}
return false;
}
int main()
{
int T;
cin>>T;
while(T--)
{
cin>>n;
for (int i = 0; i < n; i ++ )
{
int t,d,l;
cin>>t>>d>>l;
p[i]={t,d,l};
}
memset(st,0,sizeof st);
if(dfs(0,0))puts("YES");
else puts("NO");
}
return 0;
}
本题解题思路
本题第一眼觉得是贪心,但是我们看数据范围为10,再看时间限制为2s,所谓事出反常必有妖,我们知道c++一秒算八千万到一亿次,两秒最多算两亿次。那么我们究竟应该怎么算呢,我们知道如果使用暴力算法,我们需要暴力枚举10!=3680000(第一个位置有十个,第二个位置有九个……),然后每次都扫描一遍十个飞机,而且询问最多十次。所以最多三亿多次,这个看起来用两秒会超时,但是实际上我们并不是每一次都需要全部枚举出来,当遇到不能安排飞机降落的时候,我们可以直接返回,所以实际根本不需要计算三亿多次
那么我们有了思路以后,我们怎么实现代码呢,因为每个飞机有三个属性,一个达到上空的时间(T),以及剩余的油量能继续盘旋的时间(D),和降落所需要的时间(L),所以我们需要定义一个结构体,里面包含这三个属性,也就是
struct plane
{
int t,d,l;
}
由于最大只有十架飞机,所以我们需要定义一个数组,但是我习惯将数组开大一点,所以我选择开十五个
(ps:其实这里三个属性,我们可以选择pair
同时我们这里需要开一个bool数组,来记录飞机是否降落。
接下来我们开始进行暴力,我们这里选择dfs(int u,int last),里面的参数为已经起飞了u架飞机,第u架飞机在last时间成功降落。接下来我们将继续写dfs里面的内容。
首先就是我们最想要的情况,也就是当u==n的时候(n架飞机已经成功降落),这时候我们返回true。如果u!=n,我们将继续搜索下去,也就是暴力,将每一架飞机都搜索一下。当这架飞机没有降落过,我们先判断一下这架飞机的最晚降落时间(也就是d+l)是否在当前传入的last的时间之后,如果在last之后,我们可以先将这架飞机设置为开始降落,也就是st[i]=true,接着继续dfs,这里的u的参数很明显传入的是u+1(这架飞机已经降落了,所以一共降落了u+1架),但是我们这里需要思考一下第二个参数是什么呢?那么这里我们已经知道,last<=d+l,这里就有两种情况(实际上有三种情况,当last==t的时候)
我们因为要都降落,所以我们需要前面一个飞机降落之后,第二架飞机需要立刻降落,所以我们需要取last和T之间的最大值,也就是max(last,T),然后降落需要L个时间,所以我们需要传入的参数为dfs(u+1,max(last,T)+L).
当dfs到底,我们需要递归的将飞机的状态复原,也就是st[i]=false.
至此,大部分我们都写完了,但是这里有一个很关键的问题,就是每次输入的时候需要将所有的飞机的状态设置成为false。
状态压缩dp
代码如下:
#include
#include
#include
using namespace std;
const int N = 10, M = 1 << N, INF = 0x3f3f3f3f;
int dp[M];
struct plane{
int t,d,l;
}p[N];
int main()
{
int n;
int T;
cin>>T;
while(T--)
{
cin>>n;
for(int i=0;i>t>>d>>l;
p[i]={t,d,l};
}
memset(dp,0x3f,sizeof dp);
dp[0]=0;
for(int i=1;i<1<>j&1)
{
int last=dp[i-(1<=last)
dp[i]=min(dp[i],max(t,last)+l);
}
}
}
if(dp[(1<