Tom is playing a game called Idiomatic Phrases Game. An idiom consists of several Chinese characters and has a certain meaning. This game will give Tom two idioms. He should build a list of idioms and the list starts and ends with the two given idioms. For every two adjacent idioms, the last Chinese character of the former idiom should be the same as the first character of the latter one. For each time, Tom has a dictionary that he must pick idioms from and each idiom in the dictionary has a value indicates how long Tom will take to find the next proper idiom in the final list. Now you are asked to write a program to compute the shortest time Tom will take by giving you the idiom dictionary.
5 5 12345978ABCD2341 5 23415608ACBD3412 7 34125678AEFD4123 15 23415673ACC34123 4 41235673FBCD2156 2 20 12345678ABCD 30 DCBF5432167D 0
17-1
这个题我的思路是:把每个成语两端看做短点建图,即每个成语就涉及两个短点和这两个短点构成的一条边,然后用邻接表存下来,起点就是第一个成语左端的数字,终点就是最后一个成语左端的数字,然后spfa 或者 dijkstra 求最短路。但是有一个问题,假如有以下样例:
2
2 123422222222
2 123422222227
输出是错误的,原因在于起点可能会与终点重合,所以为解决这个问题,我将起点设为10000;这是4位16进制数达不到的,就解决了上述问题。
#include<cstdio> #include<cstring> #include<map> #include<cmath> #include<algorithm> #include<string> #include<iostream> #include<queue> using namespace std; const int inf = 0x3f3f3f3f; typedef struct node{ int to,v; int next; }node; node side[2001000]; int head[200100]; int len = 1; void add(int x,int y,int v) { side[len].to = y; side[len].v = v; side[len].next = head[x]; head[x] = len; len++; } int charToInt(char s[]) //转化4位16进制数 { int num = 0; for(int i = 0; i < 4; i++) { int tmp; if(s[i] >= '0' && s[i] <= '9') tmp = s[i] - '0'; else tmp = s[i] - 'A' + 10; num = num *16 + tmp; } return num; } int inq[200100]; int dis[200100]; void spfa(int be,int ed) { memset(inq,0,sizeof(inq)); memset(dis,inf,sizeof(dis)); dis[be] = 0; queue <int> q; q.push(be); while(!q.empty()) { int tmp = q.front(); q.pop(); inq[tmp] = 0; for(int i = head[tmp];i!=-1;i=side[i].next) { int to = side[i].to; int v = side[i].v; if(dis[tmp]+v < dis[to]) { dis[to] = v+dis[tmp]; if(!inq[to]) q.push(to); } } } if(dis[ed] == inf) printf("-1\n"); else printf("%d\n",dis[ed]); } int main() { int n,m; char s[1500]; while(scanf("%d",&n)&&n) { int ed; memset(head,-1,sizeof(head)); len = 1; for(int i = 0; i < n; i++) { scanf("%d%s",&m,s); int x = charToInt(s); int y = charToInt(s+strlen(s) - 4); if(i == 0) add(100000,y,m); else add(x,y,m); if(i == n-1) ed = x; } spfa(100000,ed); } return 0; }