• POJ1860 Currency Exchange bellman


    该题是给定某一货币,然后再给定一些兑换的条件,问能否使得钱币总数增加,是不是非常诱人呢?

    对该题的一个转化就是如果在转化的过程中出现了环的话,那么我们就可以在这个环内不停的进行转化,以致钱币数量无穷大,再反过来兑换就可以得到原始的币种了,而且一定会增加。

    利用bellman算法能过得到是否存在环,由于最长的环的路径长度是N-1(N各节点)所以我们只要对所有的边进行N-1次松弛,然后再看是否还可以继续松弛来判断是否有环的形成。

    代码如下:

    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #define MAXN 205
    using namespace std;
    
    int N, M, S, cnt;
    double V, dis[MAXN];
    
    struct edge
    {
        int a, b;
        double r, c;    
    }e[MAXN];
     
    bool bellman()
    {
        memset(dis, 0, sizeof (dis));
        memset(hash, 0, sizeof (hash));
        dis[S] = V;
        hash[S] = 1;
        for (int j = 1; j <= N-1; ++j) {
            for (int i = 1; i <= cnt; ++i) { // 遍历所有的边  
                if ((dis[ e[i].a ]-e[i].c)*e[i].r - dis[ e[i].b ] > 1e-6) { 
                    dis[ e[i].b ]= (dis[ e[i].a ]-e[i].c)*e[i].r;
             // 不能够在此处进行visit判断是否成环,因为可能在一次更新中更新两次 } } }
    for (int i = 1; i <= cnt; ++i) { if ((dis[ e[i].a ]-e[i].c)*e[i].r - dis[ e[i].b ] > 1e-6) { return 1; } } return 0; } int main() { int a, b; double rab, cab, rba, cba; while (scanf("%d %d %d %lf", &N, &M, &S, &V) == 4) { cnt = 0; for (int i = 0; i < M; ++i) { scanf("%d %d %lf %lf %lf %lf", &a, &b, &rab, &cab, &rba, &cba); ++cnt; e[cnt].a = a, e[cnt].b = b, e[cnt].r = rab, e[cnt].c = cab; ++cnt; e[cnt].a = b, e[cnt].b = a, e[cnt].r = rba, e[cnt].c = cba; } printf(bellman()? "YES\n":"NO\n"); } }
  • 相关阅读:
    规约先行-(十五)索引规约
    规约先行-(十四)建表规约
    规约先行-(十三)安全规约
    规约先行-(十二)单元测试
    异常日志-(十一)日志规约
    异常日志-(十)异常处理
    10.25-ROS2安装
    安装sensor-sdk
    jz2440操作速查
    新版本uboot启动流程分析
  • 原文地址:https://www.cnblogs.com/Lyush/p/2571102.html
Copyright © 2020-2023  润新知