Currency Exchange (判断负环,代码极短)

题目

        Several currency exchange points are working in our city. Let us suppose that each point specializes in two particular currencies and performs exchange operations only with these currencies. There can be several points specializing in the same pair of currencies. Each point has its own exchange rates, exchange rate of A to B is the quantity of B you get for 1A. Also each exchange point has some commission, the sum you have to pay for your exchange operation. Commission is always collected in source currency. 
For example, if you want to exchange 100 US Dollars into Russian Rubles at the exchange point, where the exchange rate is 29.75, and the commission is 0.39 you will get (100 - 0.39) * 29.75 = 2963.3975RUR. 

        我们城市有几个货币兑换点在运作。让我们假设每个点专门针对两种特定货币,并且仅使用这些货币执行交换操作。同一对货币可以有多个点。每个点都有自己的汇率,A对B的汇率是1A的B数量。此外,每个兑换点都有一定的佣金,即您必须为兑换业务支付的金额。佣金总是以来源货币收取。 例如,如果你想在汇率为29.75,佣金为0.39的兑换点将100美元兑换成俄罗斯卢布,你将得到(100-0.39)*29.75=2963.3975卢布。

         你肯定知道在我们城市有N种不同的货币可以交易。让我们为每种货币分配从1到N的唯一整数。然后,每个兑换点可以用6个数字来描述:整数A和B——它兑换的货币数量,以及实际RAB、CAB、RBA和CBA——A兑换B和B兑换A时的汇率和佣金。

尼克有一些S币的钱,他想知道在一些兑换业务之后,他是否能以某种方式增加他的资本。当然,他最终还是想把钱换成S货币。帮助他回答这个难题。尼克在做手术的时候必须有一笔非负的钱。

输入

         输入的第一行包含四个数字:N - 货币数量,M - 兑换点数,S - Nick 拥有的货币数量和 V - 他拥有的货币单位数量。以下 M 行每行包含 6 个数字 - 对应交换点的描述 - 按照上面指定的顺序。数字由一个或多个空格分隔。1<=S<=N<=100,1<=M<=100,V为实数,0<=V<=103. 

        每个点的汇率和佣金都是真实的,小数点后最多两位数字,10-2 <=率<=10 2, 0<=佣金<=102如果在此序列中没有多次使用交换点,我们称一些交换操作序列为简单。您可以假设在任何简单的交换操作序列结束时和开始时总和的数值之比将小于 104

 输出

         如果Nick可以增加他的财富,则输出YES,在其他情况下,将NO输出到输出文件。

 样本输入

3 2 1 20.0
1 2 1.00 1.00 1.00 1.00
2 3 1.10 1.00 1.10 1.00

 样本输出

YES

题意

        就是最短路的输入,只不过不给1到2的距离了,改成了计算,开始你在一个点(不一定是点1),往外随便走,回来你是否钱多了?(所以也可以不停地走两个点

题目链接:Currency Exchange 

方法一:(模拟过程)

开始用的遍历(n只有100),一旦往回一步和原来比增大了,就无限套娃,双飞上天,直接标记成YES,WA了几发发现不对,要是一个圈增大不就没戏了,这样想还是太多漏洞

        所以直接往里走,dist [ i ]记录 点i 最大金额,多遍历几次,最后去比较初始点的钱 多了还是少了

下面是Bellman-Ford算法遍历的

 代码

#include<bits/stdc++.h>
using namespace std;
#define M 105
int n,m,k,a[M],b[M];
double dist[M],res;
struct Node{
    double a1,b1,a2,b2;
}c[M];
int main()
{
    scanf("%d%d%d%lf",&n,&m,&k,&res);         ///弄清dist[i]的意思是关键
    dist[k]=res;
    for(int i=1;i<=m;i++)
        scanf("%d%d%lf%lf%lf%lf",&a[i],&b[i],&c[i].a1,&c[i].b1,&c[i].a2,&c[i].b2);
    for(int i=1;i<=n*n;i++)     //n*n只是次数,该题数据需要n*n次
        for(int j=1;j<=m;j++){
        dist[b[j]]=max(dist[b[j]],(dist[a[j]]-c[j].b1)*c[j].a1);    //首尾互相更新
        dist[a[j]]=max(dist[a[j]],(dist[b[j]]-c[j].b2)*c[j].a2);
    }
    if(dist[k]>res) cout<<"YES"<<endl;         ///最后判断和开始时是否增大
    else cout<<"NO"<<endl;
    return 0;
}


方法二:(判断负环)

把价格增加比作负环(即有一个不停增大的环路),只需判断有无即可,而方法还是很经典的Bellman-Ford算法,最后判断即可

bool fin(){
    for(int i=1;i<=m;i++)     //邻接表储存路
        if(dist[b[i]]>dist[a[i]]+c[i])
            return true;
    return false; 
}

代码

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
#define M 105
int n,m,k,a[M],b[M];
double dist[M],res;
struct Node{
    double a1,b1,a2,b2;
}c[M];
bool solve(){
    for(int i=1;i<=m;i++)
        if((dist[b[i]]<(dist[a[i]]-c[i].b1)*c[i].a1)||(dist[a[i]]<(dist[b[i]]-c[i].b2)*c[i].a2))
        return true;
    return false;
}
int main()
{
    scanf("%d%d%d%lf",&n,&m,&k,&res);
    dist[k]=res;
    for(int i=1;i<=m;i++)
        scanf("%d%d%lf%lf%lf%lf",&a[i],&b[i],&c[i].a1,&c[i].b1,&c[i].a2,&c[i].b2);
    for(int i=1;i<n;i++)
        for(int j=1;j<=m;j++){
        dist[b[j]]=max(dist[b[j]],(dist[a[j]]-c[j].b1)*c[j].a1);
        dist[a[j]]=max(dist[a[j]],(dist[b[j]]-c[j].b2)*c[j].a2);
    }
    if(solve()) cout<<"YES"<<endl;
    else cout<<"NO"<<endl;
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

int 我

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值