POJ - 1860 货币兑换(bellman)
题目:
传送门
我们城市有几个货币兑换点。让我们假设每个点专门研究两种特定的货币,并且只与这些货币进行兑换操作。可以有多个点专门用于同一对货币。每个点都有自己的汇率,A到B的汇率就是1A得到B的数量。此外,每个交换点都有一些佣金,即您必须为交换操作支付的金额。佣金始终以来源货币收取。
例如,如果您想在兑换点将 100 美元兑换成俄罗斯卢布,汇率为 29.75,佣金为 0.39,您将获得 (100 - 0.39) * 29.75 = 2963.3975RUR。
您肯定知道在我们的城市中您可以处理 N 种不同的货币。让我们为每种货币分配从 1 到 N 的唯一整数。那么每个兑换点可以用 6 个数字来描述:整数 A 和 B - 它兑换的货币数量,以及真实的 R AB , C AB , R BA和 C BA - 分别将 A 兑换成 B 和 B 兑换 A 时的汇率和佣金.
尼克有一些货币 S 的钱,想知道他是否可以在一些交换操作后以某种方式增加他的资本。当然,他最终想把钱换成货币S。帮助他回答这个难题。尼克在开展业务时必须始终拥有非负金额。
输入
输入的第一行包含四个数字:N - 货币数量,M - 兑换点数,S - Nick 拥有的货币数量和 V - 他拥有的货币单位数量。以下 M 行每行包含 6 个数字 - 对应交换点的描述 - 按照上面指定的顺序。数字由一个或多个空格分隔。1<=S<=N<=100,1<=M<=100,V为实数,0<=V<=10 3。
每个点的汇率和佣金都是真实的,小数点后最多两位数字,10 -2 <=rate<=10 2 , 0<=commission<=10 2。
如果在此序列中没有多次使用交换点,我们称一些交换操作序列为简单。您可以假设在任何简单交换操作序列的末尾和开头的总和的数值之比将小于 10 4。
输出
如果尼克可以增加他的财富,输出YES,否则输出NO到输出文件。
题意分析
- 钱币交换一圈后总钱数增加
- 也就是查看图中是否有正环
- 我们知道bellman可以查找负环,那么正环只需要改进一下就可以
#include<iostream>
#include<cstring>
using namespace std;
typedef double d;
const int N=201;
int n,m,s,a,b,all;
struct no
{
int a,b;
d r,c;
}mp[N];
d rab,cab,rba,cba,v,dis[N];
int bell()
{
memset(dis,0,sizeof(dis));
dis[s]=v;
while(dis[s]<=v)
{
int flag=0;
for(int i=0; i<all; i++)
{
if(dis[mp[i].b]<(dis[mp[i].a]-mp[i].c)*mp[i].r)//查找正环
{
dis[mp[i].b]=(dis[mp[i].a]-mp[i].c)*mp[i].r;
flag=1;
}
}
if(!flag) return 0;
}
return 1;
}
int main()
{
while(cin>>n>>m>>s>>v)
{
while(m--)
{
cin>>a>>b>>rab>>cab>>rba>>cba;
mp[all].a=a;//将数据存入结构体
mp[all].b=b;
mp[all].r=rab;
mp[all++].c=cab;
mp[all].a=b;
mp[all].b=a;
mp[all].r=rba;
mp[all++].c=cba;
}
if(bell()) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}
更多推荐
所有评论(0)