ZOJ 2750 -- Idiomatic Phrases Game(Dijkstra)
ZOJ 2750 -- Idiomatic Phrases Game(Dijkstra)
题意 :
给定一本字典,字典里有很多成语,要求从字典里的第一个成语开始,运用字典里的成语变到最后一个成语,变得过程就是成语接龙,后一个成语的第一个字必须有前一个成语的最后一个字相等,给定的成语是4位16进制位,每个成语前边跟的数字代表着找到这个成语之后再找到下个成语还需要t分钟 。
思路 :
将所有的成语看成一个点,如果找到下一个成语,就建一条有向边,然后用dijkstra求最短路。
1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 const int maxn = 1000+5;///N (0 < N < 1000) 5 const int INF = 1000000000;//无穷大 6 struct node{ 7 char front[5],back[5];///front[4]和back[4]用来存放结束符'\0' 8 int T;///用来存放边的权重,从这个成语到其他成语所需的时间 9 }; 10 int Edge[maxn][maxn];//邻接矩阵 11 int dist[maxn];//用来存储原点到i结点的最短路径 12 int S[maxn]; 13 int n;///字典中成语的数量 14 node dic[maxn]; 15 16 void solve_case(int v0) 17 { 18 ///建图 19 for(int i=0;i<n;i++) 20 { 21 for(int j=0;j<n;j++) 22 {//判断从i->j是否有单向路径 23 Edge[i][j] = INF; 24 if(i==j) continue; 25 if(strcmp(dic[i].back,dic[j].front) == 0){ 26 Edge[i][j] = dic[i].T; 27 } 28 } 29 } 30 31 ///Dijkstra算法 32 for(int i=0;i<n;i++) //初始化 33 { 34 dist[i] = Edge[v0][i];S[i] = 0; 35 } 36 dist[v0] = 0;S[v0] = 1;///将源点加入S 37 38 for(int i=0;i<n-1;i++)///寻找n-1条最短路 39 { 40 int min = INF,u=0; 41 for(int j=0;j<n;j++)///寻找一个具有最短路的结点u 42 { 43 if(!S[j] && dist[j]<min) 44 { 45 min = dist[j];u = j; 46 } 47 } 48 S[u] = 1; 49 ///更新与结点u能到达的点 50 for(int j=0;j<n;j++) 51 { 52 if(Edge[u][j]<INF && dist[u]+Edge[u][j]<dist[j]){ 53 dist[j] = dist[u] + Edge[u][j]; 54 } 55 } 56 } 57 if(dist[n-1]==INF) cout<<-1<<endl; 58 else cout<<dist[n-1]<<endl; 59 } 60 61 int cin_case() 62 { 63 while(cin>>n && n) 64 { 65 char arr[100]; 66 for(int i=0;i<n;i++) 67 { 68 cin>>dic[i].T>>arr; 69 int len = strlen(arr); 70 for(int j=0,k=len-1;j<4;j++,k--) 71 {///将读入的成语的第一个和第二个汉字存入字典 72 dic[i].front[j] = arr[j]; 73 dic[i].back[3-j] = arr[k]; 74 } 75 //////////一定要注意加字符结束符/////////// 76 dic[i].front[4] = dic[i].back[4] = '\0'; 77 /////////////////////////////////////////// 78 } 79 return 1; 80 } 81 return 0; 82 } 83 84 int main() 85 { 86 while(cin_case()) 87 { 88 solve_case(0); 89 } 90 91 return 0; 92 }