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
****************************************************************/