仲裁 POJ - 2240(SPFA判断正环)

仲裁 POJ - 2240
套利是利用货币汇率的差异将一个单位的货币转换为多个单位的同种货币。例如,假设1美元买0.5英镑,1英镑买10.0法郎,1法郎买0.21美元。然后,通过转换货币,聪明的交易者可以从 1 美元开始,买入 0.5 * 10.0 * 0.21 = 1.05 美元,赚取 5% 的利润。

您的工作是编写一个程序,该程序将货币汇率列表作为输入,然后确定是否可以进行套利。
输入
输入将包含一个或多个测试用例。在每个测试用例的第一行有一个整数 n (1<=n<=30),代表不同货币的数量。接下来的 n 行每行包含一种货币的名称。在名称中不会出现空格。下一行包含一个整数 m,表示要遵循的表格的长度。最后 m 行每行包含源货币的名称 ci、代表从 ci 到 cj 的汇率的实数 rij 和目标货币的名称 cj。没有出现在表中的交换是不可能的。
测试用例之间由一个空行分隔。输入以 n 的零 (0) 值终止。
输出
对于每个测试用例,分别以“Case case: Yes”和“Case case: No”格式打印一行,说明是否可以进行套利。
3
USDollar
BritishPound
FrenchFranc
3
USDollar 0.5 BritishPound
BritishPound 10.0 FrenchFranc
FrenchFranc 0.21 USDollar

3
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 USDollar

0
Sample Output
Case 1: Yes
Case 2: No
思路:每种钱看成一个点,要获利,就是需要正环,(dis全为0,起点初始值要大,dis每次取大的,一个点进队超n次则,就是有环),map把每个货币的字符串转化为一个记号,方便我们存下来运算。

#include<iostream>
#include<cstring>
#include<map>
#include<queue>
using namespace std;
const int N=100;
int n,m;
int vist[N],head[N],book[N],cnt;
double dis[N];
struct Edge{
	int to;
	double w;
	int next;
}edge[N*N];
void into()
{
	memset(vist,0,sizeof(vist));
	memset(head,-1,sizeof(head));
	memset(book,0,sizeof(book));
	fill(dis,dis+N,0);
	cnt=0;
}
void add_edge(int u,int v,double w)
{
	edge[cnt].to=v;
	edge[cnt].w=w;
	edge[cnt].next=head[u];
	head[u]=cnt++;
}
bool SPFA()
{
	queue<int> q;
	q.push(1);
	vist[1]=1;
	book[1]++;
	dis[1]=1000;
	while(!q.empty()){
		int cur=q.front();
		q.pop();
		vist[cur]=0;
		for(int i=head[cur];~i;i=edge[i].next){
			int next=edge[i].to;
			
			if(dis[next]<dis[cur]*edge[i].w){
				dis[next]=dis[cur]*edge[i].w;
				if(!vist[next]){
					q.push(next);
					vist[next]=1;
					book[next]++;
			if(book[next]>=n) return true;
				}
			}
		}
	}
	return false;	
}
int main()
{
	ios::sync_with_stdio(false);
	int i,j,time=0;
	double w;
	string s1,s2;
	
	while(cin>>n&&n){
		into();
		map<string,int> mp;
		for(i=1;i<=n;i++){
			cin>>s1;
			mp[s1]=i;
		}
		cin>>m;
		for(i=1;i<=m;i++){
			cin>>s1>>w>>s2;
			add_edge(mp[s1],mp[s2],w);
		}
		time++;
		cout<<"Case "<<time<<":";
		if(SPFA()){
			cout<<" Yes"<<endl;
		}
		else cout<<" No"<<endl;
	}
}

floyd

#include<iostream>
#include<cstring>
#include<map>
using namespace std;
int n,m;
double e[50][50];
bool floyd()
{
	int i,j,k;
	for(k=1;k<=n;k++){
		for(i=1;i<=n;i++){
			for(j=1;j<=n;j++){
				e[i][j]=max(e[i][j],e[i][k]*e[k][j]);//注意每次取最大的
			}
		}
	}
	for(i=1;i<=n;i++){
		if(e[i][i]>1.0) return true;//跑一次后,汇率增加,所以就是有正环。
	}
	 return false;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int i,j,k,time=0;
	double x;
	while(cin>>n&&n){
		map<string,int> mp;
		string s,s1,s2;
		for(i=1;i<=n;i++){
			cin>>s;
			mp[s]=i;
			e[i][i]=1;//初始自己到自己为1,即汇率不变
		}
		cin>>m;
		for(i=1;i<=m;i++){
			cin>>s1>>x>>s2;
			e[mp[s1]][mp[s2]]=x;
		}
		time++;
		cout<<"Case "<<time<<":";
		if(floyd()){
			cout<<" Yes"<<endl;
		}
		else cout<<" No"<<endl;
		
	}
 } 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值