HDU - 1546 Idiomatic Phrases Game

题目:
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.
Input
The input consists of several test cases. Each test case contains an idiom dictionary. The dictionary is started by an integer N (0 < N < 1000) in one line. The following is N lines. Each line contains an integer T (the time Tom will take to work out) and an idiom. One idiom consists of several Chinese characters (at least 3) and one Chinese character consists of four hex digit (i.e., 0 to 9 and A to F). Note that the first and last idioms in the dictionary are the source and target idioms in the game. The input ends up with a case that N = 0. Do not process this case.
Output
One line for each case. Output an integer indicating the shortest time Tome will take. If the list can not be built, please output -1.
Sample Input
5
5 12345978ABCD2341
5 23415608ACBD3412
7 34125678AEFD4123
15 23415673ACC34123
4 41235673FBCD2156
2
20 12345678ABCD
30 DCBF5432167D
0
Sample Output
17
-1
代码如下:

#include<bits/stdc++.h>
using namespace std;
#define MAX 1005
#define NIL 0x3f3f3f3f
int t,mp[MAX][MAX],dis[MAX];
bool vis[MAX];
struct Node
{
    int x;
    char str1[5],str2[5];
}node[MAX];
void Dijkstra()
{
    memset(dis,NIL,sizeof(dis));
    memset(vis,false,sizeof(vis));
    dis[0] = 0;
    priority_queue<int> q;
    q.push(0);
    while(!q.empty()){
        int flag = q.top();
        q.pop();
        vis[flag] = true;
        for(int i = 0;i < t;i++){
            if(dis[i] > dis[flag] + mp[flag][i]){
                dis[i] = dis[flag] + mp[flag][i];
                q.push(i);
            }
        }
    }
}
int main()
{
    char a[MAX];
    while(~scanf("%d",&t) && t){
        for(int i = 0;i < t;i++){
            cin >> node[i].x >> a;
            int len = strlen(a);
            for(int j = 0;j < 4;j++){
                node[i].str1[j] = a[j];//将单词的前四个字母保存
                node[i].str2[3 - j] = a[--len];//将单词的后四个字母保存
            }
            node[i].str1[4] = '\0';//字符数组结束的标志,一定要加
            node[i].str2[4] = '\0';
        }
        memset(mp,NIL,sizeof(mp));
        for(int i = 0;i < t;i++){
            for(int j = 0;j < t;j++){
                if(!strcmp(node[i].str2,node[j].str1)) mp[i][j] = node[i].x;//找出路径,用邻接矩阵保存
            }
        }
        Dijkstra();//然后就是普通的Dijkstra算法
        if(dis[t - 1] == 0x3f3f3f3f) cout << "-1" << endl;//这里的结点序号是0到t - 1,所以t - 1是最后一个结点
        else cout << dis[t - 1] << endl;
    }
    return 0;
}

题意:
简单来说,第一行n代表结点个数,之和n行代表由一个数字和一个单词组成,数字代表结点i到其他相连结点的权值,如果一个单词的最后4个字母和另外一个单词的前4个单词完全的相同,那么证明这两点是联通的。
思路:
每次输入时候,用结构体储存,然后把每个单词的前四个字母和最后四个字母保存下来(这里需要做一下处理,具体过程上述代码有注释)。然后我后面用的是Dijkstra算法完成的,只不过这里结点的序号是0到t - 1。

猜你喜欢

转载自blog.csdn.net/qq_41998938/article/details/88901108