题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);
}