1124: 成语接龙

1124: 成语接龙

时间限制: 1 Sec 内存限制: 32 MB
提交: 19 解决: 6

题目描述

小明在玩成语接龙的游戏。成语接龙的规则是,如果成语A的最后一个汉字与成语B的第一个汉字相同,那么成语B就可以接到成语A的后面。
小明现在手上有一本成语词典,每次他都得花费一定时间来从当前的成语查到下一个可以接在后面的成语。
现在给你一个成语列表,请你计算从列表中的第一个成语开始,到接到列表中的最后一个成语最少需要多长时间。

输入

输入包含多组测试数据。
每组输入第一行是一个整数N(0 < N < 1000),表示成语列表的长度。
接下来N行,每行先输入一个整数T,再输入一个字符串S。
S表示一条成语,T表示小明从S查到下一个成语所花费的时间。
每条成语由至少3个汉字组成,每个汉字由4个十六进制数(0~9和A~F)组成。
当N=0时,输入结束。

输出

对于每组输入,输出从列表中的第一个成语开始,到接到列表中的最后一个成语需要的最少时间。
如果无法连接到列表中的最后一个成语,则输出-1。

样例输入

5
5 12345978ABCD2341
5 23415608ACBD3412
7 34125678AEFD4123
15 23415673ACC34123
4 41235673FBCD2156
2
20 12345678ABCD
30 DCBF5432167D
0

样例输出

17
-1

利用Dijkstra寻找最短路径问题,我把每个成语开头结尾的汉字的十六进制数转化为十进制数,即为结点号,就转化为求从第一个成语的结尾字结点到最后一个成语开头字结点的最短路径问题。别忘了加上第一个成语开头到结尾的距离。

代码

#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;

const int MAXV = 65600;
const int INF = 0x3fffffff;
struct Node {
    int v, dis;
};
vector<Node> Adj[MAXV];
int n, N;
int d[MAXV];
bool vis[MAXV] = {false};
void Dijkstra(int s){ 
    fill(d, d + MAXV, INF);
    d[s] = 0;
    for(int i = 0; i <= N; i++){ 
        int u = -1, MIN = INF; 
        for(int j = 0; j <= N; j++){
            if(vis[j] == false && d[j] < MIN){
                u = j;
                MIN = d[j];
            }
        }
        if(u == -1) return;
        vis[u] = true; 
        for(int j = 0; j < Adj[u].size(); j++){
            int v = Adj[u][j].v;
            if(vis[v] == false && d[u] + Adj[u][j].dis < d[v]){
                d[v] = d[u] + Adj[u][j].dis;
            }
        } 
    } 
}

int start(string a) {
    int s = 0, tmp;
    for(int i = 0; i < 4; i++) {
        if(a[i] >= '0' && a[i] <= '9') tmp = a[i] - '0';
        else tmp = a[i] - 'A' + 10;
        s = s * 16 + tmp;
    }
    return s;
}
int end(string a) {
    int s = 0, tmp;
    for(int i = a.length() - 4; i < a.length(); i++) {
        if(a[i] >= '0' && a[i] <= '9') tmp = a[i] - '0';
        else tmp = a[i] - 'A' + 10;
        s = s * 16 + tmp;
    }
    return s;   
}
int main() {
    while(cin >> n) {
        if(n == 0) break;
        fill(vis, vis + MAXV, false);
        for(int i = 0; i < n; i++){
            Adj[i].clear();
        }
        int s, e, first_time, ds;
        N = 0;
        bool flag = false;
        for(int i = 0; i < n; i++) {         
            Node tmp;
            cin >> tmp.dis;
            string a;
            cin >> a;
            int st, ed;         
            st = start(a), ed = end(a);
            if(st > N) N = st;
            if(ed > N) N = ed;
            tmp.v = ed;
            Adj[st].push_back(tmp);     
            if(i == 0) {
                if(st == ed){
                    flag = true;
                    ds = tmp.dis;
                } 
                s = ed;
                first_time = tmp.dis;
            }
            if(i == n - 1) {
                e = st;
            }           
        }
        Dijkstra(s);
        if(flag) {
            d[s] = ds;
        }
        if(n == 1) {
            cout << 0 << endl;
         }
        else if(d[e] != INF)
            cout << d[e] + first_time << endl;
        else
            cout << -1 << endl;                      
    }
    return 0;
}
/**************************************************************
    Problem: 1124
    User: 14041045
    Language: C++
    Result: 正确
    Time:0 ms
    Memory:3876 kb
****************************************************************/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值