这段时间要沉迷刷题一段时间了,就让CSDN陪我一起吧!
一、题目大意
套利是利用货币汇率的差异将一个货币单位转换为同一货币的一个以上单位。例如,假设1美元买入0.5英镑,1英镑买入10.0法国法郎,1法国法郎买入0.21美元。然后,通过兑换货币,聪明的交易者可以从1美元开始买入0.5 * 10.0 * 0.21 = 1.05美元,获利5%。
你的工作是编写一个程序,将一系列货币汇率作为输入,然后确定套利是否可能。
题目输入第一行是一个整数,表示货币的种类数N,接下来的N行是N个不含空格的字符串,表示N中货币。然后一行是一个整数M,表示有M种兑换途径,接下来的M行表示详细的兑换途径,其中每一行形式为: a b c,a为源货币,b为汇率,c为目的货币。
二、题目思路以及AC代码
对于这道题,我的思想是经过一下几个步骤的:首先,这是一个图论题;然后,是一个与环有关的问题;最后,好的,Bellman-Ford或SPFA。
可能有些唐突,但确实是有效的,嘿嘿,就这样我20分钟就A了这道题。言归正传,其实我想的也不无道理,对于这道题,理解题意后,无非就是让你求个环,这个环要保证边上权值之积大于1,想到这,也应该是Bellman-Ford或SPFA了。
下面给出AC代码:
Bellman-Ford:
#include <iostream>
#include <string>
#include <cstring>
#include <map>
#define MAXN 35
using namespace std;
int N, M;
struct Edge { // edge
int u, v;
};
double edges[MAXN][MAXN];
double price[MAXN];
Edge e[900];
bool BellmanFord() {
price[1] = 1;
for (int i = 1; i < N; i++) {
for (int j = 0; j < M; j++) {
int u = e[j].u;
int v = e[j].v;
if (price[v] < price[u] * edges[u][v]) {
price[v] = price[u] * edges[u][v];
}
}
}
// check loop
for (int i = 0; i < M; i++) {
int u = e[i].u;
int v = e[i].v;
if (price[v] < price[u] * edges[u][v]) {
return true; // find the loop
}
}
return false;
}
int main()
{
int Case = 0;
while (scanf("%d", &N) != EOF) {
Case++;
if (!N) break;
map<string, int> mp;
for (int i = 1; i <= N; i++) {
string tmp;
cin >> tmp;
mp[tmp] = i;
}
scanf("%d", &M);
for (int i = 0; i < M; i++) {
string a, b;
double c;
cin >> a >> c >> b;
edges[mp[a]][mp[b]] = c;
e[i].u = mp[a];
e[i].v = mp[b];
}
if (BellmanFord())
printf("Case %d: Yes\n", Case);
else
printf("Case %d: No\n", Case);
}
return 0;
}
SPFA:
#include <iostream>
#include <queue>
#include <vector>
#include <map>
#include <string>
#include <cstring>
#define MAXN 35
using namespace std;
int N, M;
struct Edge {
int v;
double cost;
Edge(int next, double c) {
v = next;
cost = c;
}
};
vector<Edge> nodes[MAXN];
double price[MAXN];
int cnt[MAXN];
bool vis[MAXN];
void init() {
for (int i = 0; i < MAXN; i++) {
nodes[i].clear();
price[i] = 0;
cnt[i] = 0;
vis[i] = false;
}
}
bool SPFA() {
price[1] = 1;
queue<int> q;
q.push(1);
vis[1] = true;
while (!q.empty()) {
int x = q.front(); q.pop();
vis[x] = false;
int size = nodes[x].size();
for (int i = 0; i < size; i++) {
int v = nodes[x][i].v;
double cost = nodes[x][i].cost;
if (price[v] < price[x] * cost) {
price[v] = price[x] * cost;
if (!vis[v]) {
vis[v] = true;
q.push(v);
cnt[v]++;
if (cnt[v] >= N) {
return true; // have loop
}
}
}
}
}
return false;
}
int main()
{
int Case = 0;
while (scanf("%d", &N) != EOF) {
init();
Case++;
if (!N) break;
map<string, int> mp;
for (int i = 1; i <= N; i++) {
string tmp;
cin >> tmp;
mp[tmp] = i;
}
scanf("%d", &M);
for (int i = 1; i <= M; i++) {
string a, b;
double c;
cin >> a >> c >> b;
Edge tmp(mp[b], c);
nodes[mp[a]].push_back(tmp);
}
if (SPFA())
printf("Case %d: Yes\n", Case);
else
printf("Case %d: No\n", Case);
}
return 0;
}
如有问题,欢迎大家指正!!