目录
一、理想火车站定位
问题描述
小F是A市的市长,正在计划在A市新建一个火车站以方便市民的日常出行。市区内的街道布局十分规整,形成网格状。从一个位置[x1, y1]
到另一个位置[x2, y2]
的距离计算方法为 |x1 - x2| + |y1 - y2|
,即曼哈顿距离。
在初步考察后,市政府列出了M
个可能的火车站建设点。为了使得市民到火车站的总旅行时间最短,小F希望选出一个最优位置作为火车站的地址。
请你帮助小F计算出哪一个位置最适合建设新火车站。
N
: 市民的总人数。M
: 可建设火车站的备选位置数。citizens
: 一个列表,每个元素是一个元组[x_i, y_i]
,表示第i
位市民的居住位置。locations
: 一个列表,每个元素是一个元组[p_i, q_i]
,表示第i
个备选的火车站位置。
如果有多个火车站最优,那么选择第一次出现的那个。
测试样例
样例1:
输入:
n = 4,m = 3,citizens = [[-1, -1], [-1, 1], [1, -1], [1, 1]],locations = [[3, 2], [1, 0], [0, 0]]
输出:[1, 0]
样例2:
输入:
n = 2,m = 2,citizens = [[0, 0], [0, 4]],locations = [[0, 2], [0, 3]]
输出:[0, 2]
样例3:
输入:
n = 3,m = 1,citizens = [[10, 10], [20, 20], [30, 30]],locations = [[15, 15]]
输出:[15, 15]
样例4:
输入:
n = 5,m = 3,citizens = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]],locations = [[4, 5], [6, 7], [8, 9]]
输出:[4, 5]
样例5:
输入:
n = 6,m = 2,citizens = [[10, 10], [20, 20], [30, 30], [40, 40], [50, 50], [60, 60]],locations = [[35, 35], [45, 45]]
输出:[35, 35]
解题思路:
问题理解
我们需要在给定的 M
个备选位置中,选择一个位置作为火车站的地址,使得所有市民到火车站的总旅行时间(曼哈顿距离)最短。
数据结构选择
citizens
: 一个列表,每个元素是一个元组[x_i, y_i]
,表示第i
位市民的居住位置。locations
: 一个列表,每个元素是一个元组[p_i, q_i]
,表示第i
个备选的火车站位置。
算法步骤
-
初始化:
- 设置一个变量
min_distance
来记录当前最小的总距离,初始值设为无穷大。 - 设置一个变量
best_location
来记录当前最佳位置,初始值设为一个无效的位置(例如[-1, -1]
)。
- 设置一个变量
-
遍历所有备选位置:
- 对于每一个备选位置
loc
,计算所有市民到该位置的总距离。 - 计算总距离的方法是遍历所有市民,累加每个市民到该位置的曼哈顿距离。
- 对于每一个备选位置
-
更新最佳位置:
- 如果当前备选位置的总距离小于
min_distance
,则更新min_distance
和best_location
。
- 如果当前备选位置的总距离小于
-
返回结果:
- 遍历完所有备选位置后,返回
best_location
。
- 遍历完所有备选位置后,返回
最终代码:
#include <iostream>
#include <vector>
#include <limits> // 用于获取无穷大值
std::vector<int> solution(int n, int m, std::vector<std::vector<int>> citizens, std::vector<std::vector<int>> locations) {
int min_distance = std::numeric_limits<int>::max(); // 初始化最小距离为无穷大
std::vector<int> best_location = {-1, -1}; // 初始化最佳位置
for (const auto& loc : locations) { // 遍历所有备选位置
int total_distance = 0; // 当前备选位置的总距离
for (const auto& citizen : citizens) { // 遍历所有市民
int distance = abs(citizen[0] - loc[0]) + abs(citizen[1] - loc[1]); // 计算曼哈顿距离
total_distance += distance; // 累加总距离
}
// 若当前位置的总距离小于已记录的最小距离,进行更新
if (total_distance < min_distance) {
min_distance = total_distance; // 更新最小距离
best_location = loc; // 更新最佳位置
}
}
return best_location; // 返回最佳位置
}
bool vectorEqual(std::vector<int> a, std::vector<int> b) {
if (a.size() != b.size()) {
return false;
}
for (size_t i = 0; i < a.size(); ++i) {
if (a[i] != b[i]) {
return false;
}
}
return true;
}
int main() {
std::vector<std::vector<int>> citizens1 = {
{-1, -1}, {-1, 1}, {1, -1}, {1, 1}};
std::vector<std::vector<int>> locations1 = {
{3, 2}, {1, 0}, {0, 0}};
std::vector<int> result = solution(4, 3, citizens1, locations1);
std::cout << (vectorEqual(result, {1, 0}) ? "True" : "False") << std::endl;
return 0;
}
运行结果:
二、数字魔法的加一操作
问题描述
数字魔法师小U发现了一种特殊的数字变换魔法。这个魔法可以对一个数字字符串进行"进位"操作。每次操作规则如下:
- 对字符串中的每个数字进行加一操作
- 当某位数字为9时,加一后变成 0,并在前面补 1
例如:
- "798" 经过一次操作变成 "8109"(7→8, 9→0并向前增加一个1, 8→9)
- "999" 经过一次操作变成 "101010"
现在给定一个数字字符串 num_str
(长度为n)和操作次数 k
,请计算经过 k
次操作后得到的最终结果。由于结果可能非常大,请将答案对 1000000007
(10^9 + 7) 取模。
输入
- 第一行包含两个整数 n 和 k(1 ≤ n ≤ 50, 1 ≤ k ≤ 100)
- 第二行包含一个长度为n的数字字符串 num_str,仅由数字0-9组成
返回
- 返回一个整数,表示最终结果对 1000000007 取模后的值
测试样例
样例1:
输入:
n = 3 ,k = 1 ,num_str = "798"
返回:8109
解释:798 经过一次操作变成 8109
样例2:
输入:
n = 3 ,k = 3 ,num_str = "798"
返回:103221
- 第一次操作:798 → 8109
- 第二次操作:8109 → 92110
- 第三次操作:92110 → 103221
样例3:
输入:
n = 4 ,k = 3 ,num_str = "7989"
返回:10322132
解题思路:
问题理解
我们需要对一个数字字符串进行多次"进位"操作。每次操作的规则是:
- 对字符串中的每个数字进行加一操作。
- 如果某位数字为9,加一后变成0,并在前面补1。
数据结构选择
由于我们需要频繁地在字符串的前面和后面进行插入和删除操作,使用deque
(双端队列)是一个不错的选择。deque
允许我们在两端高效地进行插入和删除操作。
算法步骤
- 初始化:将输入的数字字符串转换为
deque
,方便后续操作。 - 多次操作:
- 对于每次操作,遍历
deque
中的每个数字。 - 对每个数字进行加一操作。
- 如果数字变为10,将其变为0,并在前面补1。
- 对于每次操作,遍历
- 结果生成:
- 将
deque
中的数字重新组合成一个整数。 - 对结果取模
1000000007
。
- 将
最终代码:
#include <iostream>
#include <deque>
#include <string>
const long long MOD = 1000000007;
int solution(int n, int k, std::string numStr) {
std::deque<int> numString;
for (int i = 0; i < n; ++i) {
numString.push_back(numStr[i] - '0');
}
for (int t = 0; t < k; ++t) {
int l = numString.size();
for (int i = 0; i < l; ++i) {
int num = numString.front();
numString.pop_front();
num += 1;
if (num == 10) {
numString.push_back(1);
numString.push_back(0);
} else {
numString.push_back(num);
}
}
}
long long result = 0;
int l = numString.size();
for (int i = 0; i < l; ++i) {
result = (result * 10 + numString.front()) % MOD;
numString.pop_front();
}
return result;
}
int main() {
// You can add more test cases here
std::cout << (solution(3, 1, "798") == 8109) << std::endl;
std::cout << (solution(3, 3, "798") == 103221) << std::endl;
return 0;
}
运行结果: