美团b [编程题] 送外卖2

[编程题] 送外卖2
时间限制:1秒
空间限制:32768K
美团外卖日订单数已经超过1200万,实时调度系统是背后的重要技术支撑,其中涉及很多复杂的算法。下面的题目是某类场景的抽象。

一张 n 个点 m 条有向边的图上,有 q 个配送需求,需求的描述形式为( s_i , t_i , l_i , r_i ),即需要从点 s_i 送到 t_i, 在时刻 l_i 之后(包括 l_i)可以在 s_i 领取货物,需要在时刻 r_i 之前(包括 r_i)送达 t_i ,每个任务只需完成一次。 图上的每一条边均有边权,权值代表外卖配送员通过这条边消耗的时间。在时刻 0 有一个配送员在 点 1 上,求他最多能完成多少个配送任务。
在整个过程中,我们忽略了取餐与最后给用户递餐的时间(实际场景中这两个时间是无法省略的),只考虑花费在路程上的时间。另外,允许在一个点逗留。
输入描述:
第一行,三个正整数 n , m , q (2 ≤ n ≤ 0, 1 ≤ m ≤ 400, 1 ≤ q ≤ 10)。
接下来 m 行,每行三个正整数 u_i , v_i , c_i (1 ≤ u_i,v_i ≤ n, 1 ≤ c_i ≤ 20000),表示有一条从 u_i 到 v_i 耗时为 c_i 的有向边。
接下来 q 行,每行四个正整数 s_i , t_i , l_i , r_i (1 ≤ s_i,t_i ≤ n, 1 ≤ l_i ≤ r_i ≤ 10^6),描述一个配送任务。

输出描述:
一个整数,表示最多能完成的任务数量。

输入例子:
5 4 3
1 2 1
2 3 1
3 4 1
4 5 1
1 2 3 4
2 3 1 2
3 4 3 4

输出例子:
2

这个题啊 首先需要读懂,
一个最重要的是 ,任务不是一个一个完成的
是一条路上可以接多个任务
题读错了三四遍,最后看数据才知道 ,原来题的意思是
一个人可以接手多个任务

#include <bits/stdc++.h>
using namespace std;
int flo[100][100];
int tag[100];
int w[100];

int n,m,q;
int maxs;
int sse=0;
struct node
{
    int x,y,l,r;
}d[100];

void bfs(int s,int t,int v)
{
    //sse++;
    //if(sse>5000000) return ;
    if(t>maxs) maxs=t;
    int x,y,l,r, ts;
    //cout<<s<<' '<<t<<' '<<' '<<v<<' '<<endl;
    for(int i=0;i<q;i++)//接可以接的任务
    {
        if(w[i]||tag[i]) continue;
        x=d[i].x;
        y=d[i].y;
        l=d[i].l;
        r=d[i].r;
        ts=flo[v][x];
        int k=max(s+ts,l);
        tag[i]=1;
        for(int j=0;j<q;j++)
        {
            if(d[j].r<r&&tag[j])
                r=d[j].r;
        }
        if(k<=r) bfs(k,t,x);
        tag[i]=0;

    }
    for(int i=0;i<q;i++)//完成可以完成的
    {
        if(w[i]||!tag[i]) continue;
        x=d[i].x;
        y=d[i].y;
        l=d[i].l;
        r=d[i].r;
        ts=flo[v][y];
        //int k=max(s+ts,l);
        //cout<<x<<' '<<y<<' '<<k<<' '<<flo[x][y]<<' '<<flo[v][x]<<endl;
        if(tag[i]&&s+ts<=r)
        {
            w[i]=1;
            tag[i]=0;
            bfs(s+ts,t+1,y);
            tag[i]=1;
            w[i]=0;
        }
    }
}
int main()
{
    //freopen("in.txt","r",stdin);

    while(cin>>n>>m>>q)
    {
        memset(flo,10000,sizeof(flo));
        int x,y,z;
        for(int i=1;i<=n;i++) flo[i][i]=0;
        for(int i=0;i<m;i++)
        {
            cin>>x>>y>>z;
            flo[x][y]=min(flo[x][y],z);
            //flo[y][x]=flo[x][y];
        }

        for(int k=1;k<=n;k++)
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                {
                    if(flo[i][k]+flo[k][j]<flo[i][j])
                    {
                        flo[i][j]=flo[i][k]+flo[k][j];
                    }
                }
        //cout<<flo[6][7]<<endl;
        for(int i=0;i<q;i++)
        {
            cin>>d[i].x>>d[i].y>>d[i].l>>d[i].r;
        }
        maxs=0;
        bfs(0,0,1);
        cout<<maxs<<endl;

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值