题解 CF33B String Problem

字符串最短路。假设输入两字符串 $s,\,t$。如果 $s$ 和 $t$ 长度不同则一定不能转换,输出 $-1$。

随后首先使用 Floyd 算法计算出将每个字母转换成每个字母的最小代价,若无法转换则代价为 $+infty$。随后枚举 $s$ 和 $t$ 每个相同位置转换为相同字符的最小代价,若为 $+infty$ 则输出 $-1$,否则 $ ext{sum}$ 加上这个最小代价,将字符串 $s$ 当前位置改为这个字符。

此题有两个坑点:

  • 输入中可能有重边,需要取最小而不是直接赋值。好在 CF 出题人良心,样例 $2$ 就是这种情况,若不判断是过不了的。
  • 对于 $s_i$ 和 $t_i$,不一定只有将 $s_i$ 变为 $t_i$ 和将 $t_i$ 变为 $s_i$ 才是最值,需要枚举每个字母,计算最小值。

$ ext{Code}$:

 1 const int N = 30;
 2 const int inf = 0x3f3f3f3f;
 3 
 4 int m, sum;
 5 string s, t;
 6 int trans[N][N];
 7 
 8 int main() {
 9     memset(trans, 0x3f, sizeof trans);
10      cin >> s >> t >> m;
11      if(s.size() != t.size()) return puts("-1"), 0;
12      while(m--) {
13          char c, cc;
14          int d;
15          scanf(" %c %c", &c, &cc);
16          scanf("%d", &d);
17          To_min(trans[c - 'a' + 1][cc - 'a' + 1], d);
18     }
19     rep(i, 1, 26) trans[i][i] = 0;
20     rep(k, 1, 26) {
21         rep(i, 1, 26) {
22             rep(j, 1, 26) {
23                 To_min(trans[i][j], trans[i][k] + trans[k][j]);
24             }
25         }
26     }
27     rep(i, 0, s.size() - 1) {
28         int ss = s[i] - 'a' + 1, tt = t[i] - 'a' + 1;
29         int mn = inf, f;
30         rep(j, 1, 26) {
31             if(mn > trans[ss][j] + trans[tt][j]) mn = trans[ss][j] + trans[tt][j], f = j;
32         }
33         if(mn == inf) return puts("-1"), 0;
34         sum += mn, s[i] = char(f - 1 + 'a');
35     }
36     cout << sum << endl << s << endl;
37     return 0;
38 }
View Code
原文地址:https://www.cnblogs.com/BreezeEnder/p/14050577.html