1. 程式人生 > 實用技巧 >題解 CF33B String Problem

題解 CF33B String Problem

字串最短路。假設輸入兩字串 $s,\,t$。如果 $s$ 和 $t$ 長度不同則一定不能轉換,輸出 $-1$。

隨後首先使用 Floyd 演算法計算出將每個字母轉換成每個字母的最小代價,若無法轉換則代價為 $+\infty$。隨後列舉 $s$ 和 $t$ 每個相同位置轉換為相同字元的最小代價,若為 $+\infty$ 則輸出 $-1$,否則 $\text{sum}$ 加上這個最小代價,將字串 $s$ 當前位置改為這個字元。

此題有兩個坑點:

  • 輸入中可能有重邊,需要取最小而不是直接賦值。好在 CF 出題人良心,樣例 $2$ 就是這種情況,若不判斷是過不了的。
  • 對於 $s_i$ 和 $t_i$,不一定只有將 $s_i$ 變為 $t_i$ 和將 $t_i$ 變為 $s_i$ 才是最值,需要列舉每個字母,計算最小值。

$\text{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