2018 蓝桥杯省赛 B 组模拟赛(一)--- H. 封印之门

蒜头君被暗黑军团包围在一座岛上,所有通往近卫军团的路都有暗黑军团把手。幸运的是,小岛上有一扇上古之神打造的封印之门,可以通往近卫军团,传闻至今没有人能解除封印。

封印之门上有一串文字,只包含小写字母,有 k种操作规则,每个规则可以把一个字符变换成另外一个字符。经过任意多次操作以后,最后如果能把封印之门上的文字变换成解开封印之门的文字,封印之门将会开启。

蒜头君战斗力超强,但是不擅计算,请你帮忙蒜头君计算至少需要操作多少次才能解开封印之门。

输入格式

输入第一行一个字符串,长度不大于 1000,只包含小写字母,表示封印之门上的文字。

输入第二行一个字符串,只包含小写字母,保证长度和第一个字符串相等,表示能解开封印之门的文字。

输入第三行一个整数 k(0k676)

接下来 k 行,每行输出两个空格隔开的字符 ab,表示一次操作能把字符 a 变换成字符 b

输出格式

如果蒜头君能开启封印之门,输出最少的操作次数。否则输出一行 1

样例输入
abcd
dddd
3
a b
b c
c d
样例输出
6

解析:利用最短路Floyd传递闭包的性质。主要就是建图了,拿样例举例,a b,表示a可以转换成b,用e[1][2] = 1表示此性质(数字是英文字母的代号),然后依次是:e[2][3] = 1, e[3][4] = 1,然后跑最短路,可以得到e[1][3] = 2, e[1][4] = 3......,跑完最短路判断对应字母之间是否可以相互转化即可,因为此时是最短的,所以是最优解,如果两个字母无法相互转化,就输出-1即可。具体请看代码!

特别注意的是有个坑点(我在代码中已经特殊标记起来了),不得不说蓝桥杯要特别仔细,不会直接出来测验结果,而自己出的测试数据又太过片面,因为一点小错误而没有AC还是很亏的,所以一定要仔细对待。

#include <stdio.h>
#include <string.h>
#define inf 0x3f3f3f3f
char c1[1005];
char c2[1005];
int e[30][30];
void init() {//初始化 
	for(int i = 1; i <= 26; i++) {
		for(int j = 1; j <= 26; j++) {
			if(i == j) e[i][j] = 0;//两个相同的字母互相转化不需要步数 
			else e[i][j] = inf;    //初始将两个字母之间的转化赋值为无穷大 
		}
	}
}
void Floyd() {//跑最短路 
	for(int k = 1; k <= 26; k++) {
		for(int i = 1; i <= 26; i++) {
			for(int j = 1; j <= 26; j++) {
				if(i == j) continue;
				if(e[i][j] > e[i][k] + e[k][j])
					e[i][j] = e[i][k] + e[k][j];
			}
		}
	}	
}
int main() {
	int n;
	char C1, C2;
	scanf("%s", c1);
	scanf("%s", c2);
	scanf("%d", &n);
	init();
	long long sum = 0;
	while(n--) {
		getchar();
		scanf("%c %c", &C1, &C2);
		if(C1 != C2)//这是一个坑点,有可能输入两个字母是相同的 !!!!!不写这个判断只能过20%
		e[C1-'a'+1][C2-'a'+1] = 1;//建图
	}
	Floyd(); 
	int m = strlen(c1);
	for(int i = 0; i < m; i++) {
		sum += e[c1[i]-'a'+1][c2[i]-'a'+1];//求出步数 
	}
	if(sum < inf) printf("%lld\n", sum);//判断通性 输出结果 
	else puts("-1");
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值