poj-1860

//2484K 16MS    G++
#include <stdio.h>
#include <string.h>
#define MAX_EXCHANGE_POINT 300
#define MAX_CURRENCY 300

struct ExchangeDetail {
    int A;
    int B;
    double R;
    double C;
};

typedef struct ExchangeDetail ExchangeDetail;

ExchangeDetail currencyExchangeInfo[MAX_CURRENCY][MAX_CURRENCY];
ExchangeDetail exchangeRelation[MAX_CURRENCY];

int exchangeRelationNum = 0;

double exchangeQuanitity[MAX_CURRENCY];

#define MINUS_INF -999999
int exchangePointNum;
int currenciesNum;
int curCurrency;
double number;
int edgeNum;

char BF() {
    // printf("BF\n");
    for (int i = 1; i <= currenciesNum; i++) {
        exchangeQuanitity[i] = MINUS_INF;
    }
    exchangeQuanitity[curCurrency] = number;

    for (int i = 1; i <= currenciesNum - 1; i++) {
        for (int j = 1; j <= edgeNum; j++) {
            int A = exchangeRelation[j].A;
            int B = exchangeRelation[j].B;
            double R = exchangeRelation[j].R;
            double C = exchangeRelation[j].C;
            double quanityAfterExchanged;
            if (exchangeQuanitity[A] == MINUS_INF) { // no need  to relax
                quanityAfterExchanged = MINUS_INF; // MINUS_INF + any is still MINUS_INF
            } else {
                quanityAfterExchanged = (exchangeQuanitity[A] - C) * R;
            }
                double orginal = exchangeQuanitity[B];
                if (quanityAfterExchanged > orginal) { // can relax;
                    exchangeQuanitity[B] = quanityAfterExchanged;
                }
        }
    }

    for (int i = 1; i <= edgeNum; i++) {
        int A = exchangeRelation[i].A;
        int B = exchangeRelation[i].B;
        double R = exchangeRelation[i].R;
        double C = exchangeRelation[i].C;
        double quanityAfterExchanged;
        if (exchangeQuanitity[A] == MINUS_INF) { // no need  to relax
            quanityAfterExchanged = MINUS_INF;
        } else {
            quanityAfterExchanged = (exchangeQuanitity[A] - C) * R;
        }
        double orginal = exchangeQuanitity[B];
        if (quanityAfterExchanged > orginal) { // can relax;
            return 1;
        }
    }
    // printf("BF end\n");
    return 0;
}

int main() {
    memset(currencyExchangeInfo, 0, sizeof(currencyExchangeInfo));
    memset(exchangeRelation, 0, sizeof(exchangeRelation));
    exchangeRelationNum = 0;
    edgeNum = 0;
    scanf("%d %d %d %lf", ¤ciesNum, &exchangePointNum, &curCurrency, &number);
    for(int i = 0; i < exchangePointNum; i++) {
        int currencyA;
        int currencyB;
        double RAB;
        double CAB;
        double RBA;
        double CBA;
        scanf("%d %d %lf %lf %lf %lf", ¤cyA, ¤cyB, &RAB, &CAB, &RBA, &CBA);
        currencyExchangeInfo[currencyA][currencyB].R = RAB;
        currencyExchangeInfo[currencyA][currencyB].C = CAB;
        currencyExchangeInfo[currencyB][currencyA].R = RBA;
        currencyExchangeInfo[currencyB][currencyA].C = CBA;
        exchangeRelation[++edgeNum].A = currencyA;
        exchangeRelation[edgeNum].B = currencyB;
        exchangeRelation[edgeNum].R = RAB;
        exchangeRelation[edgeNum].C = CAB;
        exchangeRelation[++edgeNum].A = currencyB;
        exchangeRelation[edgeNum].B = currencyA;
        exchangeRelation[edgeNum].R = RBA;
        exchangeRelation[edgeNum].C = CBA;
    }
    char res = BF();
    if (res) {
        printf("YES\n");
    } else {
        printf("NO\n");
    }

}


2484K 16MS    G++

典型的bellman_ford运用,不过松弛的条件变了,

一开始想偏了,不知道该怎样描述图里面边的含义,后来发现想多了,每条边就

直接按照题目的含义来就可以了(及兑换的rate和commission)重要的是点的含义,每个点应该代表的含义的是

Nick带的currency(S) 兑换该点对应的currency 所能兑换的最大量。

并且题目给的input保证了Nick一定可以在兑换数次以后,还能重现兑换回最开始的currency(因为该图是一个连通图,一个点到另一个点只要有去的路,就有回来的路,所以不存在不能返回的情况,及任何情况下都可以兑换回去)。

那么要想让Nick的资本能够升值,必须在这个图中存在一个正权回路(每循环一次该回路,因为是正权回路,所以可以总资产会增加)。

那么其实只要检查图里是否存在这样的正权回路就可以了,那么判断是否有回路,就要用BF算法了,

不同的是,算导中举得BF应用场景是经典的最短路场景,而在这里却貌似要求的是最长路,、

其实是不冲突的,所谓最短/最长/以及最XX其实是针对某个条件来说的,BF求的其实是在 这个条件或者说维度上最接近(或者可以说等于)该维度极限 的路径。

 这其实才是BF的精髓,理解了这个,才能对BF题的变种进行求解,不然会一直局限于最短路这个概念。

有了这个,剩下就是写BF code了,非常简单,

要注意的是,最开始给每个node 的 dis[]赋初值时, dis[S] 不应该是最短路场景中的0,而应该是Nick初始拥有的S的数量(和0虽然数字不一样,但在含义上是一样的,

都代表了起始点的最极限状态, 最短路中,起始点的距离起始点当然是0, 而在本场景中,在起始点,没有经过任何兑换,那么必然S的数量就是起始值)。

还有就是其他Node的dis[]初始化为了无限小(因为此时还没有开始兑换),因为在实际编程中,不可能真有一个无限小,所以一般是定义一个-999999之类的数,

注意的是,这个无限小在和其他数运算以后,还应该是无限小(即还是-999999),否则可能会出现 -999997...之类的数,有时候会引起算法错误。

因此,要注意这一点,只要有无限小参与了运算,结果还应该是无限小.

最后就就是判断BF返回值了,false的话就是YES,别搞混了.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值