poj 1860 Currency Exchange(bellman思路反用)

题意是两种货币可以互相兑换,交换的时候需要交手续费。

e.g 当你用100A币交换B币时,A到B的汇率是29.75,手续费是0.39,那么你可以得到(100 - 0.39) * 29.75 = 2963.3975 B币。

求经过不定次数兑换回原来的钱能否增加。


大神的分析:

一种货币就是图上的一个点。

一个“兑换点”就是图上两种货币之间的一个兑换环,相当于“兑换方式”M的个数,是双边。

唯一值得注意的是权值,当拥有货币A的数量为V时,A到A的权值为K,即没有兑换。

而A到B的权值为(V-Cab)*Rab。

本题是“求最大路径”,之所以被归类为“求最小路径”是因为本题题恰恰与bellman-Ford算法的松弛条件相反,求的是能无限松弛的最大正权路径,但是依然能够利用bellman-Ford的思想去解题。

因此初始化d(S)=V   而源点到其他店的距离(权值)初始化为无穷小(0),当s到其他某点的距离能不断变大时,说明存在最大路径。


代码:

#include<stdio.h>

int n;//货币种数
int m;//兑换点数
int s;//持有第s种货币
double v;//s种货币的本金

int l;//总边数
double dis[101];//s到各点权值

struct exchange
{
    int a;//货币a
    int b;//货币b
    double r;//税率
    double c;//手续费
}e[202];

bool bellman()
{
    for(int i = 0; i < m; i++)
        dis[i] = 0;
    dis[s] = v;

    for(int i = 1; i <= n-1; i++)
    {
        bool over = true;
        for(int j = 0; j < l; j++)
        {
            if(dis[e[j].b] < (dis[e[j].a] - e[j].c) * e[j].r)
            {
                dis[e[j].b] = (dis[e[j].a] - e[j].c) * e[j].r;
                over = false;
            }
        }
        if(over)
        {
            break;
        }
    }
    for(int j = 0; j < l; j++)
    {
        if(dis[e[j].b] < (dis[e[j].a] - e[j].c) * e[j].r)
            return true;
    }
    return false;
}

int main()
{
    int ta, tb;
    double rab, rba, cab, cba;
    while(scanf("%d%d%d%lf", &n, &m, &s, &v)!=EOF)
    {
        l = 0;//0个边
        for(int i = 0; i < m; i++)
        {
            scanf("%d%d%lf%lf%lf%lf", &ta, &tb, &rab, &cab, &rba, &cba);
            e[l].a = ta;
            e[l].b = tb;
            e[l].r = rab;
            e[l++].c = cab;
            e[l].a = tb;
            e[l].b = ta;
            e[l].r = rba;
            e[l++].c = cba;
        }
        if(bellman())
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值