https://nanti.jisuanke.com/t/20692
封印之门
蒜头君被暗黑军团包围在一座岛上,所有通往近卫军团的路都有暗黑军团把手。幸运的是,小岛上有一扇上古之神打造的封印之门,可以通往近卫军团,传闻至今没有人能解除封印。
封印之门上有一串文字,只包含小写字母,有 kk 种操作规则,每个规则可以把一个字符变换成另外一个字符。经过任意多次操作以后,最后如果能把封印之门上的文字变换成解开封印之门的文字,封印之门将会开启。
蒜头君战斗力超强,但是不擅计算,请你帮忙蒜头君计算至少需要操作多少次才能解开封印之门。
输入格式
输入第一行一个字符串,长度不大于 10001000,只包含小写字母,表示封印之门上的文字。
输入第二行一个字符串,只包含小写字母,保证长度和第一个字符串相等,表示能解开封印之门的文字。
输入第三行一个整数 k(0 \le k \le 676)k(0≤k≤676)。
接下来 kk 行,每行输出两个空格隔开的字符 aa, bb,表示一次操作能把字符 aa 变换成字符 bb。
输出格式
如果蒜头君能开启封印之门,输出最少的操作次数。否则输出一行 -1−1。
样例输入
abcd
dddd
3
a b
b c
c d
样例输出
6
思路:开始一直以为就是一个简单的深搜,于是我用了邻接表去搜,但一直超时,最终看了大佬的代码发现竟然是一道考最短路的题。看到这句话赶紧回来写了一波,既然有可能匹配每一个,则要知道
每个点之间的距离,所以用弗洛伊德,同时存储路径时都减一个a化为整数去做。
#include <bits/stdc++.h>
using namespace std;
int mp[30][30];
int n = 28;
const int INF = 0x3f3f3f3f;
void floyd(){
	for(int k = 0; k < n; k++){
		for(int i = 0; i < n; i++){
			for(int j = 0; j < n; j++){
				if(mp[i][j] > mp[i][k] + mp[k][j])
					mp[i][j] = mp[i][k] + mp[k][j];
			}
		}
	}
} 
int main(){
	string str, mu;
	int m;
	cin >> str >> mu;
	cin >> m;
	memset(mp, INF, sizeof(mp));
	for(int i = 0; i < m; i++){
		char x, y;
		cin >> x >> y;
		mp[x - 'a'][y - 'a'] = 1;
	}
	floyd();
	int ans = 0;
	for(int i = 0; i < str.length(); i++){
		if(str[i] == mu[i])
			continue; 
		if(mp[str[i] - 'a'][mu[i] - 'a'] < INF)
			ans += mp[str[i] - 'a'][mu[i] - 'a'];
		else{
			cout << -1 << endl;
			continue;
		}
	}
	cout << ans << endl;
	return 0;
}
                    
                
                
            
        
浙公网安备 33010602011771号