首页 > 试题广场 >

另一个快递机器人

[编程题]另一个快递机器人
  • 热度指数:89 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
图森未来的员工阿伟最新研发了一款快递机器人,他投放了一台机器人在自己的小区中进行试运营。

这个小区中共有n幢楼,每幢都有一个编号;同时每幢楼都有k层,每层有一个层号。房间号则是层号加上包含前导0的两位数字拼接而成,例如:第3层的2号房间,房间号为302;第15层的58号房间,房间号为1558;第123层的4号房间,房间号为12304。

同时,因为业主的要求,小区每幢楼的层号都会跳过包含"4"和"13"的数字,因为它们不吉利。例如,4、13、49、133和134都是不吉利的数字,而123则不是不吉利的数字,因为里面没有包含连续的"13"。被跳过的数字不会有对应的层数,例如第3层的上一层是第5层,而第12层的上一层是第15层。

机器人每天会为m个住户寄送快递,住户的房间由楼号b和一个房间号r表示。快递机器人只能通过一些特定的路线在某些楼的1层之间移动,或者通过电梯在同一幢楼的不同楼层之间移动。m个住户的送货顺序是确定的并会提前给出,快递机器人只会按照顺序依次为这m个住户送货。

为了了解快递机器人的工作效率,阿伟希望知道快递机器人每天送货的预计时间。为了简化问题,他认为只有在同一幢楼的不同楼层之间移动以及不同楼的1层之间移动才会花时间。等待电梯、在同一楼层之间送货以及出发前装货的时间都可以忽略,且快递机器人的容量足以装下所有快递,而机器人和电梯的移动速度也不会因为快递的数量发生改变。

简而言之,我们只需要计算如下两种时间花费:
- 从某幢楼的1层移动到另一幢楼的1层:某些楼之间是可以直接移动的,阿伟会提前给出这些楼之间移动的时间花费。注意因为一些交通规则的原因,从a到b花费的时间和从b到a花费的时间不一定是一样的,也可能出现a可以移动到b但是b不能移动到a的情况。另外,从a移动到c花费的时间也不一定等于从a移动到b再从b移动到c的时间。
- 从某幢楼的x层移动到同一幢楼的y层:假设x层和y层之间相隔k层,那么这次移动的时间花费就是k。但是注意因为有一些层号是不存在的,所以k不一定等于|y-x|(||代表绝对值)。例如,3层和5层之间因为不存在4层所以只相隔1层,从3层移动到5层的时间花费是1而不是2。同理,因为39层和50层之间都是包含4的楼层,所以从50层移动到39层的时间花费也是1。

请注意,按照以上规则,如果当前在a楼的x层,要移动到b楼的y层,且a!=b,x!=1,y!=1,那么要经历三个步骤:
- 从a楼x层移动到a楼1层;
- 从a楼1层移动到b楼1层(有可能会经过其它楼的1层);
- 从b楼1层移动到b楼y层。

现在阿伟会按照顺序给出某天需要送货的所有住户的楼号和房间号,以及全部可以移动的楼号和在它们之间移动分别所花费的时间。机器人每天会从1号楼的1层出发,并在所有货物送完之后回到1号楼的1层结束。阿伟希望你可以写一个程序帮他计算一下这一天送货(包括回到1号楼的1层)最少所需要花费的总时间。如果无法依次到达需要送货的所有住户,输出-1。

输入描述:
输入的第1行包含三个正整数n、t和m,分别为小区内楼的数量、可以移动的路径数量以及当天要送货的住户数量。
接下来的t行(第2行到第t+1行)每行包含三个正整数x、y、d,用空格分隔,表示从x号楼的1层移动到y号楼的一层所花费的时间为d,楼号为[1, n]内的正整数。
接下来的m行(第t+2到t+m+1行)每行包含两个正整数b和r,分别表示题目描绘中的楼号b和房间号r,其中房间号是按照题目描述中的方式拼接而成的。


输出描述:
输出包含一个整数,为当天送货所需要花费的最少总时间。若当天因为无法在某两个楼之间移动而完不成送货任务,则输出-1。
示例1

输入

2 2 2
1 2 10
2 1 100
2 1501
2 314

输出

132

说明

样例中从1号楼1层走到2号楼1层花费时间为10,从2号楼1层走回1号楼1层花费时间为100。

机器人需要为两家送货,第一家为2号楼的15层1501室,第二家为2号楼的3层314室。

为第一家送货的时候,机器人会从1号楼1层出发,先走到2号楼1层,花费时间10;再从2号楼1层坐电梯到2号楼15层,1层到15层共经过11层(2、3、5、6、7、8、9、10、11、12、15,不包含4、13和14层),花费时间11。
为第二家送货的时候,机器人会从2号楼15层出发,坐电梯直接到达2号楼3层,15层到3层共经过9层(12、11、10、9、8、7、6、5、3),花费时间9。

送货完成之后,机器人还需要回到1号楼1层。机器人会从2号楼3层出发,坐电梯到达2号楼1层,花费时间2;再从2号楼1层回到1号楼1层,花费时间100。

所以总的时间花费为10+11+9+2+100=132。

备注:
设小区内楼的总数量为n,可以移动的路径数量为t,当天要送货的住户数量为m,所有建筑中最高的楼层号为f,建筑1层之间路径的最长长度为d。
对于30%的数据,1 <= n <= 100,1 <= t <= 5000,1 <= m <= 100,1 <= f <= 100,1 <= d <= 105
对于另外70%的数据,1 <= n <= 1000,1 <= t <= 10000,1 <= m <= 100,1 <= f <= 106,1 <= d <= 105
#include <cstdio>
#include <vector>
#include <map>
#include <algorithm>
#include <queue>
using namespace std;
 
typedef pair<int, long long> Edge;
typedef map<int, vector<Edge>> Graph;
int n, t, m;
const int MAXD =1000010;
const long long INF=INT64_MAX;
long long pre[MAXD];
Graph G;
 
bool valid_floor(int floor){
    vector<int> vec;
    while(floor){
        vec.push_back(floor%10);
        floor/=10;
    }
    for(int i=0;i<vec.size();i++){
        if(vec[i]==4) return false;
        if(i>0&&vec[i]==1&&vec[i-1]==3) return false;
    }
    return true;
}
 
typedef pair<long long,int> P;
long long dij(int from,int to){
    priority_queue<P, vector<P>, greater<P> > que;
    vector<long long> d(n+1,INF);
    d[from]=0;
    que.push(P(0,from));
    while(!que.empty()){
        P p=que.top();
        que.pop();
        int v=p.second;
        if(d[v]<p.first) continue;
        for(Edge e:G[v]){
            if(d[e.first]>d[v]+e.second){
                d[e.first]=d[v]+e.second;
                que.push(P(d[e.first],e.first));
            }
        }
    }
    if(d[to]==INF){
        printf("-1\n");
        exit(0);
    }
    else return d[to];
}
 
int main()
{
    for(int i=1;i<MAXD;i++){
        if(valid_floor(i)){
            pre[i]=pre[i-1]+1;
        }else{
            pre[i]=pre[i-1];
        }
    }
    scanf("%d%d%d", &n, &t, &m);
    for (int i = 0; i < t; i++)
    {
        int x, y;
        long long d;
        scanf("%d%d%lld", &x, &y, &d);
        G[x].push_back(Edge{y,d});
    }
    int lastb=1,lastr=1;
    long long cost=0;
    for(int i=0;i<m;i++){
        int b,r;
        scanf("%d%d",&b,&r);
        r/=100;
        if(b==lastb){
            cost+=abs(pre[lastr]-pre[r]);
        }else{
            cost+=pre[lastr]-pre[1];
            cost+=dij(lastb,b);
            cost+=pre[r]-pre[1];
        }
        lastb=b;
        lastr=r;
    }
    if(lastb==1){
        cost+=pre[lastr]-pre[1];
    }else{
        cost+=pre[lastr]-pre[1];
        cost+=dij(lastb,1);
    }
    printf("%lld\n",cost);
    return 0;
}


发表于 2021-07-29 15:33:24 回复(3)
#include <iostream>
#include <vector>
#include <fstream>
#include <map>
#include <algorithm>
#include <queue>
#include <set>
using namespace std;
typedef pair<int, int> Edge;
typedef map<int, vector<Edge> > Edges;
int getValue(int start, int v) {
    auto func = [](int x){
        vector<int> vec;
        while (x > 0) {
            vec.push_back(x % 10);
            x /= 10;
        }
        return vec;
    };
    auto find4 = [](vector<int>&vec) {
        for (int i = 0; i < vec.size(); ++i) 
            if (vec[i] == 4)
                return i;
        return -1;
    };
    auto find13 = [](vector<int>& vec) {
        for (int i = 1; i < vec.size(); ++i) {
            if (vec[i] == 1 && vec[i-1] == 3)
                return i-1;
        }
        return -1;
    };
    if (start == v) return 0;
    int min_ = std::min(start, v);
    int max_ = std::max(start, v);
    int n = 0;
    int id4, id13;
    for (int i = min_+1; i <= max_; ) {
        auto vec = func(i);
        int step1 = 0;
        int step2 = 0;
        if ((id4 = find4(vec)) != -1) {
            step1 = 1;
            while (id4--) step1 *= 10;
        }
        if ((id13 = find13(vec)) != -1) { 
            step2 = 1;
            while (id13--) step2 *= 10;
        }
        int step = std::max(step1, step2);
        n += !step;
        i += std::max(step, 1);
    }
    return n;
}
int func(int n, Edges& edges, vector<int>& vex, vector<int>& track) {
    vector< vector<int> > matrix;
    for (int i = 0; i < n; ++i) {
        vector<int> vec(n);
        fill(vec.begin(), vec.end(), -1);
        matrix.push_back(vec);
    }
    for (int i = 0; i < n; ++i) matrix[i][i] = 0;
    for (int i = 0; i < n; ++i) {
        queue<int> q;
        q.push(i);
        vector<int> visited(n);
        visited[i] = 1;
        while (!q.empty()) {
            int x = q.front();
            for (auto e : edges[x]) {
                if (!visited[e.first]) {
                    visited[e.first] = 1;
                    q.push(e.first);
                }
                int y = e.first;
                int d = e.second;
                if (matrix[x][y] == -1) matrix[x][y] = d;
                if (matrix[i][x] + matrix[x][y] < matrix[i][y]) {
                        matrix[i][y] = matrix[i][x] + matrix[x][y];
                }
            }
            q.pop();
        }
    }
    int res = 0;
    int last = 0;
    for (int i = 0; i < track.size(); ++i) {
        if (matrix[last][track[i]] == -1) 
            return -1;
        else {
            res += matrix[last][track[i]];
            res += vex[i];
        }
        last = track[i];
    }
    if (matrix[last][0] == -1) return -1;
    return res + matrix[last][0];
}
int main() {
    int n, t, m;
    cin >> n >> t >> m;
    vector<int> vex;
    vector<int> track;
    Edges edges;
    for (int i = 0; i < t; ++i) {
        int x, y, d;
        Edge e;
        cin >> x >> y >> d;
        e.first = y - 1;
        e.second = d;
        edges[x-1].push_back(e);
    }
    int pre = 1;
    for (int i = 0; i < m; ++i) {
        int b, r;
        cin >> b >> r;
        if (track.empty()) {
            vex.push_back(getValue(1, r/100));
            track.push_back(b-1);
            pre = r/100;
        }
        else if (track[track.size()-1] == b-1){
            vex[vex.size() - 1] += getValue(pre, r/100);
            pre = r/100;
        }
        else {
            vex[vex.size() - 1] += getValue(1, pre);
            vex.push_back(getValue(1, r/100));
            track.push_back(b-1);
            pre = r/100;
        }
    }
    vex[vex.size() - 1] += getValue(1, pre);
    cout << func(n, edges, vex, track) << endl;
}

发表于 2019-12-26 15:46:28 回复(0)