饿了么24秋招工程方向&算法方向
题目的具体描述可参考牛客牛客网
1.小红送外卖
题目描述
小红在第三新北林市的学园城送外卖,学园城中有非常多的学校,学园城里有一个美食街。小红每次会接一些同一个学校的订单,然后从美食街取餐出发,再骑车将外卖送到学校,最后回到美食街,以此往复。
学园城有 𝑛 个结点, 𝑚条道路,美食街为1号结点,剩下的结点都是学校,保证学园城中所有结点连通。给出小红每次要送外卖的学校,请计算小红最少需要骑行的距离。
分析
-
该题目要求最少骑行距离
-
也就是说,要求起点到终点的最短距离
-
但是小红每次送完外卖都会回到起点(学校),也就是说,每次都从起点开始求最短路径,然后将这些最短路径相加就是最少距离。
-
采用dijkstar算法,关于dijkstar算法可看Dijkstar-CSDN博客
-
采用dijkstar算法求出各个节点到起点的最短路径,然后将目标节点的最短路径相加。
代码
完整代码如下
- 图的存储方式采用邻接表的形式
- 采用优先队列对算法进行优化
#include <iostream>
#include <vector>
#include <queue>
#include <climits>
using namespace std;
#define INF INT_MAX
struct Edge {
int to;
int weight;
};
vector<vector<Edge>> graph;
vector<int> dijkstra(int start, int n) {
vector<int> distance(n + 1, INF);
distance[start] = 0;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
pq.push({ 0, start });
while (!pq.empty()) {
int u = pq.top().second;
int dist = pq.top().first;
pq.pop();
if (dist > distance[u]) continue;
for (const auto& edge : graph[u]) {
int v = edge.to;
int w = edge.weight;
if (distance[v] > distance[u] + w) {
distance[v] = distance[u] + w;
pq.push({ distance[v], v });
}
}
}
return distance;
}
int main() {
int n, m;
cin >> n >> m;
int num_schools;
cin >> num_schools;
graph.resize(n + 1);
// 构建图
for (int i = 0; i < m; ++i) {
int u, v, w;
cin >> u >> v >> w;
graph[u].push_back({ v, w });
graph[v].push_back({ u, w });
}
vector<int> schools(num_schools);
for (int i = 0; i < num_schools; ++i) {
cin >> schools[i];
}
// 计算从美食街到每个学校的最短距离
vector<int> distances_from_foodcourt = dijkstra(1, n);
// 计算最小距离之和
int total_distance = 0;
for (int school : schools) {
total_distance += distances_from_foodcourt[school];
}
cout << "小红最少需要骑行的距离为: " << total_distance * 2 << " 米" << endl;
return 0;
}
2.小红等外卖
题目描述
小红在饿了么上面点了一个外卖,饥肠辘辘的她等骑手等得望眼欲穿。
已知小红在时刻𝑡1点了外卖,饿了么上面显示预计送达时间为𝑡2,实际送达时间为𝑡3。请你判断外卖是否超时?
分析
-
left表示预计送达时间,right表示实际送达时间
-
如果预计送达时间在第二天,但实际送达时间在当天,则没有超时;
相反,如果预计送达时间在当天,实际送达时间在第二天,超时;
if (time[right][0] - time[left][0] >= 22) { printf("%s\n", "No"); } if (time[left][0] - time[right][0] >= 22) { printf("%s\n", "Yes"); }
-
如果实际预计送达时间和实际送达时间都在当天
-
如果预计送法时间的小时位 > 实际送达时间的小时位,则没有超时
if (time[left][0] > time[right][0]) { printf("%s\n", "No"); }
-
如果预计送法时间的小时位 = 实际送达时间的小时位
//如果如果预计送法时间的小时位 = 实际送达时间的小时位 if (time[left][0] == time[right][0]) { //预计送法时间的分数位 >= 实际送达时间的分数位,没有超时 if (time[left][1] >= time[right][1]) { printf("%s\n", "No"); } else{ printf("%s\n", "Yes"); } }
-
如果预计送达时间的小时位 < 实际送达时间的小时位,则超时
-
代码
int num2() {
int t;
cin >> t;
cin.ignore();
//定义一个vector数组存储时间
vector<vector<int>> time(3 * t, vector<int>(2, 0));
for (int i = 0; i < 3 * t; i++) {
//getline用法
string line;
getline(cin, line);
stringstream ss(line);
string temp1;
getline(ss, temp1, ':');
time[i][0] = stoi(temp1);
string temp2;
getline(ss, temp2, ':');
time[i][1] = stoi(temp2);
}
int left = 1;
int right = 2;
while (right < 3 * t) {
if (time[right][0] - time[left][0] >= 22) {
printf("%s\n", "No");
}
else if (time[left][0] - time[right][0] >= 22) {
printf("%s\n", "Yes");
}
else {
if (time[left][0] > time[right][0]) {
printf("%s\n", "No");
}
else if (time[left][0] == time[right][0]) {
if (time[left][1] >= time[right][1]) {
printf("%s\n", "No");
}
else
{
printf("%s\n", "Yes");
}
}
else {
printf("%s\n", "Yes");
}
}
left += 3;
right += 3;
}
return 0;
}
3.小红的字符串构造
题目描述
小红拿到了一个字符串𝑠,她准备构造一个和𝑠长度相同的字符串𝑡,满足以下条件:
- 𝑡的字符集和𝑠的相同(去重后的,也就是说不考虑数量)
- 𝑡的每个位置的字符都和𝑠不同。
例如若 s=“aabbc”,那么𝑡t可以构造为"cbaca"。
你能帮帮小红吗?
分析
- 本题的关键在于将字符映射
- 采用set集合剔除s字符串中相同的元素
- 采用map集合将set中元素的第二位与第三位映射、第三位与第四位映射,…,第一位与最后一位映射
代码
#include <vector>
#include <set>
#include <map>
#include <algorithm>
using namespace std;
class MyCompare {
public:
bool operator()(char a, char b) {
return a > b;
}
};
int num3() {
string str;
cin >> str;
set<char> strSet;
//采用set集合剔除str中相同的元素
for (int i = 0; i < str.size(); i++) {
strSet.insert(str[i]);
}
vector<char> v1(strSet.begin(), strSet.end());
//映射前的准备工作
//准备一个v2数组,v2数组中的元素顺序为set中的第二位、第三位、...、最后一位、第一位
vector<char> v2;
for (set<char>::iterator it = strSet.begin(); it != strSet.end(); it++) {
if (it == strSet.begin()) continue;
v2.push_back(*it);
}
v2.push_back(*strSet.begin());
//采用map集合将v1与v2中的每一个元素映射
map<char, char> m;
for (int i = 0; i < v2.size(); i++) {
m[v1[i]] = v2[i];
}
//根据映射关系找到result字符串
string result = "";
for (int i = 0; i < str.size(); i++) {
result += m[str[i]];
}
if (result.size() != str.size() || result == str) cout << -1 << endl;
else cout << result << endl;
return 0;
}