今天我们将在豆包MarsCode AI刷题平台上,完成《小R的权值计算》与《删除路径后的最短路问题》这两个算法问题,通过这些练习提升用户解决此类问题的能力
《小R的权值计算》题面如下:
问题理解
只要多写几个示例就会发现本题很简单:
对于长度为4的数组
a b c d
以当前位置为起点的所有子数组权值贡献: 1
1 2
1 2 3
1 2 3 4
1
1 2
1 2 3
1
1 2
1
对于长度为5的数组
a b c d e
以当前位置为起点的所有子数组权值贡献: 1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
1
1 2
1 2 3
1 2 3 4
1
1 2
1 2 3
1
1 2
1
很容易发现,对于位置i,所有权值的和为(n + 1 - i) * i * (i + 1) / 2,其中i * (i + 1) / 2是[1..i]这个连续等差序列的和,(n + 1 - i)是序列中每个元素出现的次数
算法步骤
依次遍历数组a中每个元素,将 元素值 和 这个位置的权值和 的乘积加到结果中
具体实现:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int mod = 1e9+7;
int solution(int n, vector<int>& a) {
// write code here
int ret=0;
for(int i=n;i>=1;i--){
ret += a[i-1] * (n+1-i) * i * (i+1)/2 % mod;
}
return ret;
}
int main() {
vector<int> a1 = {1, 2, 3};
cout << (solution(3, a1) == 33) << endl;
vector<int> a2 = {4, 5, 6, 7};
cout << (solution(4, a2) == 203) << endl;
vector<int> a3 = {10, 20};
cout << (solution(2, a3) == 80) << endl;
}
《删除路径后的最短路问题》题面如下:
问题理解
需要计算由起点 s 到终点 t 的最短路径,但不能直接通过起点和终点之间的线段。这个问题可以通过图的最短路径算法来解决,本题我们使用Dijkstra算法。
数据结构选择
- 距离数组
dist:用于存储从起点s到每个点的最短距离。初始值设为-1.0,表示距离未确定。 - 访问标记数组
vis:用于标记某个点是否已经被访问过。 - 优先队列
pq:用于实现Dijkstra算法中的优先队列,按照距离由小到大排序。
算法步骤
-
初始化:
- 将起点
s的距离设为0,并标记为已访问。 - 将起点
s加入优先队列。
- 将起点
-
Dijkstra算法:
- 在优先队列中取出当前距离最小的点
cur。 - 标记该点为已访问。
- 遍历所有其他点
nxt,计算从cur到nxt的距离。 - 如果
nxt未被访问且cur到nxt的距离小于dist[nxt],则更新dist[nxt]并将其加入优先队列。
- 在优先队列中取出当前距离最小的点
-
特殊情况处理:
- 如果起点
s和终点t相同,则需要计算从s到其他所有点的最短距离,并选择最小的距离乘以2作为结果。
- 如果起点
-
格式化输出:
- 使用
std::ostringstream和std::fixed、std::setprecision来格式化输出,保留两位小数。
- 使用
具体实现:
#include <bits/stdc++.h>
using namespace std;
double calDist(int ix, int iy, int jx, int jy){
return sqrt((ix - jx) * (ix - jx) + (iy - jy) * (iy - jy));
}
string solution(int n, int s, int t, vector<int> x, vector<int> y) {
// write code here
vector<double> dist(n,-1.0);
vector<bool> vis(n,false);
dist[s-1] = 0;
vis[s-1] = true;
// 特殊情况处理
if(s == t){
double ret = -1.0;
for(int nxt=0;nxt<n;nxt++){
if(s-1 == nxt){
continue;
}
double nxtDist = calDist(x[s-1], y[s-1], x[nxt], y[nxt]);
if(ret == -1.0){
ret = nxtDist*2.0;
} else {
ret = min(ret, nxtDist*2.0);
}
}
dist[t-1] = ret;
}
// Dijkstra算法
priority_queue<pair<double, int>, vector<pair<double, int>>, greater<pair<double, int>>> pq;
pq.push({0,s-1});
while(!vis[t-1]){
pair<double, int> cur = pq.top();
pq.pop();
vis[cur.second] = true;
for(int nxt =0;nxt<n;nxt++){
if(vis[nxt] || (cur.second == s-1 && nxt == t-1) || nxt == cur.second){
continue;
}
double nxtDist = calDist(x[cur.second], y[cur.second], x[nxt], y[nxt]);
if(dist[nxt] == -1.0 || cur.first + nxtDist < dist[nxt]){
dist[nxt] = cur.first + nxtDist;
pq.push({dist[nxt], nxt});
}
}
}
// 使用ostringstream来格式化输出
ostringstream oss;
oss << fixed << setprecision(2) << dist[t-1];
return oss.str();
}
int main() {
cout << (solution(5, 1, 5, {17253, 25501, 28676, 30711, 18651}, {15901, 15698, 32041, 11015, 9733}) == "17333.65") << endl;
cout << (solution(4, 2, 4, {5000, 12000, 8000, 14000}, {3000, 9000, 1000, 4000}) == "15652.48") << endl;
cout << (solution(6, 3, 6, {20000, 22000, 24000, 26000, 28000, 30000}, {15000, 13000, 11000, 17000, 19000, 21000}) == "11772.70") << endl;
cout << (solution(10, 2, 2, {11,3,5,6,2,4,15,14,16,8}, {5,8,7,14,8,10,5,4,2,9}) == "2.00") << endl;
return 0;
}
借助豆包MarsCode AI刷题平台,我们不仅高效地解决了《小R的权值计算》和《删除路径后的最短路问题》,还加深了对相关算法和数据结构的理解,后续会借助豆包MarsCode AI给大家展示更多题目的解法