题目概述
给定N种货币,和M条货币间的汇率,问是否可套汇
套汇是指某种货币通过和其他一系列货币兑换,最终兑换回起始币种时汇率大于1的情况
时限
1000ms/2000ms
输入
每组输入第一行正整数N,其后N行,每行一个字符串sa,代表一种货币名称,之后一行正整数M,其后M行,每行一个字符串sa,一个浮点数a,另一个字符串sb,表示1单位sa币可兑换a单位sb币,输入以N=0结束
限制
1<=N<=30;货币名称中不含空格
输出
每行一个字符串,符合以下格式
Case #: @
其中#为数据序数,@当出现套汇时为Yes,否则为No
样例输入
3
USDollar
BritishPound
FrenchFranc
3
USDollar 0.5 BritishPound
BritishPound 10.0 FrenchFranc
FrenchFranc 0.21 USDollar3
USDollar
BritishPound
FrenchFranc
6
USDollar 0.5 BritishPound
USDollar 4.9 FrenchFranc
BritishPound 10.0 FrenchFranc
BritishPound 1.99 USDollar
FrenchFranc 0.09 BritishPound
FrenchFranc 0.19 USDollar0
样例输出
Case 1: Yes
Case 2: No
讨论
图论,floyd算法,用单源最短路也能做,不过那个有点忘却,floyd倒是门清着(毕竟简单),无非就是检查一下有没有环,若有环,查一下绕一圈的权值积是否大于1
输入的数据有字符串,常见的接地气的(放水)表现,弄个字符串到整型的单映射就够了,不过不能用char*比较烦人,还得用string+cin
题解状态
249MS,1816K,985 B,C++
题解代码
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<map>
#include<string>
#include<iostream>
using namespace std;
#define INF 0x3f3f3f3f
#define MAXN 32
#define memset0(a) memset(a,0,sizeof(a))
map<string, int>cur;//currency 货币名称到数字的单映射
string sa, sb;//string_a string_b 据说声明字符串很费时 那就循环利用好了
double mat[MAXN][MAXN];//matrix floyd辅助矩阵
int times;//控制Case输出
void fun(int N)
{
for (int p = 0; p < N; p++) {
cin >> sa;//input
cur[sa] = p;//建立一个映射
}
int M;//货币兑换条目数
cin >> M;//input
for (int p = 0; p < M; p++) {
double a;//汇率
cin >> sa >> a >> sb;//input
mat[cur[sa]][cur[sb]] = a;//初始化floyd矩阵
}
for (int p = 0; p < N; p++)
for (int i = 0; i < N; i++)
for (int u = 0; u < N; u++)
mat[i][u] = max(mat[i][u], mat[i][p] * mat[p][u]);//floyd的经典三重循环 这里不是加法 是乘法
for (int p = 0; p < N; p++)
if (mat[p][p]>1.0) {//到自身汇率大于1便是套汇
printf("Case %d: Yes\n", ++times);
return;//有一组就够
}
printf("Case %d: No\n", ++times);
}
int main(void)
{
//freopen("vs_cin.txt", "r", stdin);
//freopen("vs_cout.txt", "w", stdout);
int N;//币种数
while (cin >> N&&N) {//input
fun(N);
cur.clear();
memset0(mat);
}
}