计蒜客 封印之门(思维+Floyd)

传送门


思路:

    个人感觉是很巧妙的一题啊,总觉得很熟悉但就是差点意思...

   首先分析一下bfs是没戏了,每个字母最多26中变换方法(可以自己变成自己),最长1000,26^1000 ,hhh 

    感觉这题加深了对Floyd的理解吧,由于是小写字母也就是最多有26个城市,我们可以先不去考虑整个字符串,只看把某个字符变为要求的字符需要几步,然后在遍历整个串求出总共需要的步数即可.我们把每一次操作变换看成是一条权值为1的有向边,就发现这是个多元最短路问题了(其实给定你k次变换操作,就相当于是给你了k条右向边啊。)

#include <bits/stdc++.h>

#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 30;
string st,dt;
ll mp[30][30],k;
int main()
{
	while(cin >> st >> dt >> k)
	{
		for(int i = 0;i <= 26;++i)
		{
			for(int j = 0;j <= 26;++j)
			{
				if(i == j) 
					mp[i][i] = 0;
				else
					mp[i][j] = inf;
			}
		}
		for(int i = 1;i <= k;++i)
		{
			char s1[5],s2[5];
			scanf("%s %s",s1,s2);
			if(s1[0] == s2[0]) continue;
			mp[s1[0] - 'a'][s2[0] - 'a'] = 1;
		}
		for(int kk = 0;kk < 26;++kk)
			for(int i = 0;i < 26;++i)
				for(int j = 0;j < 26;++j)
					mp[i][j] = min(mp[i][j],mp[i][kk] + mp[kk][j]);
		bool flag = 1;
		ll ans = 0;
		for(int i = 0;i < st.size();++i)
		{
			ll dis = mp[st[i] - 'a'][dt[i] - 'a'];
			if(dis >= inf)
			{
				flag = 0;
				break;
			}
			ans += dis;
		}
		if(flag)
			printf("%lld\n",ans);
		else
			puts("-1");
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/howardemily/article/details/79763563