用C++解决以下问题:开学的第一天小 M 迫不及待地计划着前往神秘的禁林。小 M 拥有两个重要的属性魔力值和生命值。非常特别的是初始时这两个值可以由小 M 任意决定。禁林可以看作一张 n 个点 m 条边的无向简单连通图。小 M 将在禁林里面行走从起点 s 走到 t。每经过一条边小 M 的魔力值都会减去 1。同时每条边上有一个具有攻击力属性的魔兽小 M 要与之战斗。若小 M 经过这条边之前的魔力值为
首先,我们可以使用 Dijkstra 算法求解小 M 从起点 s 到终点 t 的最短路径。在 Dijkstra 算法中,我们使用一个优先队列来存储待处理的节点,每次取出队列中距离起点最近的节点进行处理。
在算法中,我们需要维护每个节点的最小魔力值和最小生命值。我们可以使用一个二维数组 dp[i][j] 来表示节点 i 的最小魔力值和最小生命值,其中 dp[i][j] 表示在魔力值为 j 的情况下,到达节点 i 所需的最小生命值。
初始时,我们将所有的 dp[i][j] 设置为无穷大,表示不可达。然后,将起点 s 的 dp[s][j] 设置为 j,表示魔力值为 j 的情况下,到达起点 s 不消耗生命值。
接下来,我们开始进行 Dijkstra 算法的主循环。每次从优先队列中取出距离起点最近的节点 u 进行处理。对于节点 u 的每个邻接节点 v,如果通过边 uv 可以使得 v 的 dp[v][k] 更新为更小的值,我们将 v 加入到优先队列中,并更新 dp[v][k] 的值。
在更新 dp[v][k] 的过程中,我们需要考虑当前边 uv 上的魔兽攻击力 w。根据题目要求,我们需要计算出经过边 uv 时消耗的生命值为 w/k 向下取整。因此,我们可以将 dp[v][k] 更新为 dp[u][j] + max(w/k, 1),表示通过边 uv 后,到达节点 v 的最小生命值。
最终,当我们处理完所有的节点后,dp[t][j] 中的最小值即为小 M 初始时需要的最小生命值。
下面是使用 C++ 实现的代码:
#include <iostream>
#include <vector>
#include <queue>
#include <limits>
using namespace std;
struct Edge {
int to;
int weight;
};
typedef pair<int, int> pii;
int dijkstra(vector<vector<Edge>>& graph, int start, int end) {
int n = graph.size();
vector<vector<int>> dp(n, vector<int>(101, numeric_limits<int>::max()));
priority_queue<pii, vector<pii>, greater<pii>> pq;
dp[start][0] = 0;
pq.push({0, start});
while (!pq.empty()) {
pii curr = pq.top();
pq.pop();
int dist = curr.first;
int u = curr.second;
if (dist > dp[u][dist]) {
continue;
}
for (const Edge& edge : graph[u]) {
int v = edge.to;
int w = edge.weight;
for (int k = 0; k <= 100; ++k) {
if (dist + max(w / k, 1) < dp[v][k]) {
dp[v][k] = dist + max(w / k, 1);
pq.push({dp[v][k], v});
}
}
}
}
int minLife = numeric_limits<int>::max();
for (int k = 0; k <= 100; ++k) {
minLife = min(minLife, dp[end][k]);
}
return minLife;
}
int main() {
int n, m;
cin >> n >> m;
vector<vector<Edge>> graph(n);
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});
}
int s, t;
cin >> s >> t;
int minLife = dijkstra(graph, s, t);
cout << minLife << endl;
return 0;
}
在上述代码中,我们使用了优先队列来实现 Dijkstra 算法的最小堆。同时,我们使用了邻接表来表示图的结构,并使用了一个二维数组来存储每个节点的最小魔力值和最小生命值
原文地址: http://www.cveoy.top/t/topic/ivsj 著作权归作者所有。请勿转载和采集!