问题 : 成语接龙
时间限制: 1 Sec 内存限制: 32 MB题目描述
小明在玩成语接龙的游戏。成语接龙的规则是,如果成语A的最后一个汉字与成语B的第一个汉字相同,那么成语B就可以接到成语A的后面。
小明现在手上有一本成语词典,每次他都得花费一定时间来从当前的成语查到下一个可以接在后面的成语。
现在给你一个成语列表,请你计算从列表中的第一个成语开始,到接到列表中的最后一个成语最少需要多长时间。
小明现在手上有一本成语词典,每次他都得花费一定时间来从当前的成语查到下一个可以接在后面的成语。
现在给你一个成语列表,请你计算从列表中的第一个成语开始,到接到列表中的最后一个成语最少需要多长时间。
输入
输入包含多组测试数据。
每组输入第一行是一个整数N(0<N<1000),表示成语列表的长度。
接下来N行,每行先输入一个整数T,再输入一个字符串S。
S表示一条成语,T表示小明从S查到下一个成语所花费的时间。
每条成语由至少3个汉字组成,每个汉字由4个十六进制数(0~9和A~F)组成。
当N=0时,输入结束。
每组输入第一行是一个整数N(0<N<1000),表示成语列表的长度。
接下来N行,每行先输入一个整数T,再输入一个字符串S。
S表示一条成语,T表示小明从S查到下一个成语所花费的时间。
每条成语由至少3个汉字组成,每个汉字由4个十六进制数(0~9和A~F)组成。
当N=0时,输入结束。
输出
对于每组输入,输出从列表中的第一个成语开始,到接到列表中的最后一个成语需要的最少时间。
如果无法连接到列表中的最后一个成语,则输出-1。
如果无法连接到列表中的最后一个成语,则输出-1。
样例输入
5
5 12345978ABCD2341
5 23415608ACBD3412
7 34125678AEFD4123
15 23415673ACC34123
4 41235673FBCD2156
2
20 12345678ABCD
30 DCBF5432167D
0
样例输出
17
-1
解题思路
这道题其实就是一道最短路问题;可以先把每个成语的头和尾分别存起来,然后暴力寻找头接尾的耗时,最后利用最短路的方法就行了。具体见代码:
#include <stdio.h> #include <string.h> const int inf = 99999999; int ans[1001], map[1001][1001], arr[1001], vis[1001]; char str[100], left[1001][5], right[1001][5]; int main() { int t, i, j, k, len, data, min; while (scanf("%d", &t), t) { for (i = 0; i < t; i++) { scanf("%d%s", &ans[i], str); len = strlen(str); for (j = 0; j < 4; j++) left[i][j] = str[j]; for (j = 0; j < 4; j++) right[i][j] = str[len + j - 4]; left[i][4] = right[i][4] = '\0'; } for (i = 0; i < t; i++) { for (j = 0; j < t; j++) { if (i == j) map[i][j] = 0; else map[i][j] = inf; if (!strcmp(right[i], left[j])) map[i][j] = ans[i]; } } for (i = 0; i < t; i++) { vis[i] = inf; arr[i] = 0; } vis[0] = 0; for (i = 0; i < t; i++) { min = inf; for (j = 0; j < t; j++) { if (!arr[j] && vis[j] < min) { min = vis[j]; data = j; } } arr[data] = 1; for (k = 0; k < t; k++) { if (map[data][k] < inf) { if (!arr[k] && vis[k] > vis[data] + map[data][k]) vis[k] = vis[data] + map[data][k]; } } } if (vis[t - 1] == inf) puts("-1"); else printf("%d\n", vis[t - 1]); } return 0; }