《小R的权值计算》和《删除路径后的最短路问题》| 豆包MarsCode AI刷题

131 阅读4分钟

今天我们将在豆包MarsCode AI刷题平台上,完成《小R的权值计算》与《删除路径后的最短路问题》这两个算法问题,通过这些练习提升用户解决此类问题的能力

《小R的权值计算》题面如下:

图片.png

问题理解

只要多写几个示例就会发现本题很简单:

对于长度为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;
}

《删除路径后的最短路问题》题面如下:

图片.png

问题理解

需要计算由起点 s 到终点 t 的最短路径,但不能直接通过起点和终点之间的线段。这个问题可以通过图的最短路径算法来解决,本题我们使用Dijkstra算法。

数据结构选择

  1. 距离数组 dist:用于存储从起点 s 到每个点的最短距离。初始值设为 -1.0,表示距离未确定。
  2. 访问标记数组 vis:用于标记某个点是否已经被访问过。
  3. 优先队列 pq:用于实现Dijkstra算法中的优先队列,按照距离由小到大排序。

算法步骤

  1. 初始化

    • 将起点 s 的距离设为 0,并标记为已访问。
    • 将起点 s 加入优先队列。
  2. Dijkstra算法

    • 在优先队列中取出当前距离最小的点 cur
    • 标记该点为已访问。
    • 遍历所有其他点 nxt,计算从 curnxt 的距离。
    • 如果 nxt 未被访问且 curnxt 的距离小于 dist[nxt],则更新 dist[nxt] 并将其加入优先队列。
  3. 特殊情况处理

    • 如果起点 s 和终点 t 相同,则需要计算从 s 到其他所有点的最短距离,并选择最小的距离乘以2作为结果。
  4. 格式化输出

    • 使用 std::ostringstreamstd::fixedstd::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给大家展示更多题目的解法