Floyd 求最短路
2023年12月24日 12:13
解法:Floyd 求最短路
本题使用到了 Floyd 求最短路算法。关于这个算法,我给力扣专栏写过一篇文章进行了详细的介绍,欢迎有兴趣的读者阅读:https://zhuanlan.zhihu.com/p/623757829
由于本题只能将单个字符改为其它字符,所以不同位置之间的修改互不影响,那么答案就是把 source[i] 改成 target[i] 的代价加起来,即 $\sum\limits_{i = 1}^n g(s_i, t_i)$,其中 $g(s_i, t_i)$ 是把字符 $s_i$ 改成 $t_i$ 的最小代价。
我们把每个字母看成一个点,如果能把字母 $x$ 改成字母 $y$,就从 $x$ 到 $y$ 连一条长度为 cost[i] 的有向边。这样对于任意两个字母 $x$ 和 $y$,把 $x$ 改成 $y$ 的最小代价就是从 $x$ 到 $y$ 的最短路。
由于我们需要知道任意两个点之间的最短路,所以可以使用 Floyd 算法。
复杂度 $\mathcal{O}(n + m + \Sigma^3)$,其中 $n$ 是 source 的长度,$m$ 是 original 的长度,$\Sigma$ 是字符集的大小,即 $26$。
参考代码(c++)
###c++
class Solution {
public:
long long minimumCost(string source, string target, vector<char>& original, vector<char>& changed, vector<int>& cost) {
const int INF = 1e9;
// 建有向图
long long g[26][26];
for (int i = 0; i < 26; i++) for (int j = 0; j < 26; j++) g[i][j] = INF;
for (int i = 0; i < 26; i++) g[i][i] = 0;
for (int i = 0; i < original.size(); i++) {
int x = original[i] - 'a', y = changed[i] - 'a';
g[x][y] = min(g[x][y], 1LL * cost[i]);
}
// floyd 求最短路
for (int k = 0; k < 26; k++) for (int i = 0; i < 26; i++) for (int j = 0; j < 26; j++)
g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
long long ans = 0;
// 把每个位置的修改代价加起来
for (int i = 0; i < source.size(); i++) {
int x = source[i] - 'a', y = target[i] - 'a';
if (x != y) {
// x 不能变成 y,无解
if (g[x][y] >= INF) return -1;
// 否则答案增加把 x 改成 y 的最小代价
ans += g[x][y];
}
}
return ans;
}
};