飞机降落 暴力出奇迹

数据范围很小直接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;
}

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值