阿里2017算法工程师在线笔试编程——8月25日

题1:周期开放点的最短路问题

题目描述:给定拓扑结构,两点间距离,源点,汇点,每个节点周期性开放关闭,各点周期不同。
求:源点到汇点的最短时间。
例子:
9
0 3
1 5
2 7
3 3
4 5
5 7
6 9
7 3
8 5
14
0 1 4
0 7 8
1 2 8
1 7 11
2 3 7
2 5 4
2 8 2
3 4 9
3 5 14
4 5 10
5 6 2
6 8 6
6 7 1
7 8 7
0
4

点数
点数 周期

边数
边起点 边汇点 距离

源点
汇点

解释:9个点,1编号点,周期5,0时刻开启,5时刻关闭,10时刻开启,依次类推。如到达ID_1点在时刻5,则需要等待到时刻10。到达于时刻4,则立即出发。
最短路问题,可用动态规划,因为到达其中任何一个点的最短路径(包括在该点等待时间)可用Dijkstra里的思想求。
代码:
#include <iostream>
#include <vector>
#include <list>
#include <queue>
#include <functional>
#include <numeric>
#include <limits>

using namespace std;

/** 请完成下面这个函数,实现题目要求的功能 **/
/** 当然,你也可以不按照这个模板来作答,完全按照自己的想法来 ^-^  **/
int minTravelTime(int N, vector < vector < int > > intersections, int M, vector < vector < int > > roads, int s, int t) {
    int ans = 0;
    //read T
    vector<int> T(N);
    for (auto &it1 : intersections) {
        T[it1[0]] = it1[1];
    }

    //read adjlist
    using edge = pair<int, int>;
    vector<list<edge>> adjlist(N);
    for (auto &rd : roads) {
        adjlist[rd[0]].emplace_back(make_pair(rd[1], rd[2]));
    }

    //make priority_queue
    using distid = pair<int, int>;
    priority_queue<distid, vector<distid>, greater<distid> > q;

    //make dist vector
    vector<int> dist(N,INT_MAX),done(N,0);
    dist[s] = 0;

    q.push(make_pair(dist[s], s));

    while (!q.empty()) {
        auto u = q.top();
        q.pop();
        int id = u.second;
        if (done[id])continue;
        done[id] = 1;
        for (const auto &p : adjlist[id]) {
            int tt = T[p.first];//周期
            int tmp = u.first + p.second;//到达u.first点的时间
            if ((tmp / tt) & 1)tmp = (tmp / tt + 1)*tt;//考虑周期
            if (tmp < dist[p.first]) {
                if (p.first == t)ans = u.first+p.second;
                dist[p.first] = tmp;
                q.push(make_pair(dist[p.first], p.first));
            }
        }
    }
    return ans;//到达的时间 
    //注:这里记不清求的是可以离开t的最短时间还是到达t的最短时间
    return dist[t];//可以离开的时间
}

int main() {//读取函数是编程平台给的
// #ifdef _WIN32 for debug
//  freopen("in.txt", "r", stdin);
// #endif // _WIN32
    int res;

    int _N;
    cin >> _N;
    cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

    int _intersections_rows = _N;
    int _intersections_cols = 2;

    vector< vector < int > > _intersections(_intersections_rows);
    for (int _intersections_i = 0; _intersections_i < _intersections_rows; _intersections_i++) {
        for (int _intersections_j = 0; _intersections_j < _intersections_cols; _intersections_j++) {
            int _intersections_tmp;
            cin >> _intersections_tmp;
            _intersections[_intersections_i].push_back(_intersections_tmp);
        }
    }
    int _M;
    cin >> _M;
    cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

    int _roads_rows = _M;
    int _roads_cols = 3;

    vector< vector < int > > _roads(_roads_rows);
    for (int _roads_i = 0; _roads_i < _roads_rows; _roads_i++) {
        for (int _roads_j = 0; _roads_j < _roads_cols; _roads_j++) {
            int _roads_tmp;
            cin >> _roads_tmp;
            _roads[_roads_i].push_back(_roads_tmp);
        }
    }
    int _s;
    cin >> _s;
    cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

    int _t;
    cin >> _t;
    cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

    res = minTravelTime(_N, _intersections, _M, _roads, _s, _t);
    cout << res << endl;
// #ifdef _WIN32
//  fclose(stdin);
// #endif // _WIN32
    return 0;

}

题2:菜鸟仓库货架编号问题

题目描述:一个数字代表一个货架。如下编码:1|12|123|1234|12345|……|12345678910111213141516|
求:第K个货物的代表数字是几。例如第三个货物是2,第10个货物是4。
/** 请完成下面这个函数,实现题目要求的功能 **/
/** 当然,你也可以不按照这个模板来作答,完全按照自己的想法来 ^-^  **/

#include <stdio.h>  
#include <math.h>  
#include <stdlib.h>
#define getN(x) ((int)log10(x)+1)
using ull = unsigned long long;
ull summ[5000];//5000足够K最大值
void pre_calc() {
    ull tmp[5000] = { 0 };
    tmp[1] = summ[1] = 1;
    for (int i = 2; i < 5000; i++)
    {
        tmp[i] = tmp[i - 1] + getN(i);//每个格子的长度
        summ[i] = summ[i - 1] + tmp[i];//累计长度
    }
}
int Get(int n) {
    int i = 1, position, len;
    while (summ[i] < n)i++;//找到格子
    position = n - summ[i - 1];//在格子中的偏移
    len = 0;
    for (i = 1; len < position; i++) {
        len += getN(i);
    }
    //找到那个货架所在的数i-1,及在这个数中的位数,len-position,=0:个位,=1:十位
    // do something
    int x = (i - 1) / (int)pow(10, len - position) % 10;
    return x;
}

int main()
{
    pre_calc();
    int n;
    scanf("%d", &n);
    int r = Get(n);

    printf("%d\n", r);
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值