zoukankan      html  css  js  c++  java
  • 货币兑换

    题意:有若干种货币,某些币种之间可兑换,给出各种兑换时的汇率和手续费,任何兑换都是双向的,但是两个方向的汇率和手续费可能不同,并告知你现在拥有的货币种类(只拥有一种)及数量,问是否可以通过货币建兑换最后回到本币种后钱数有所增加。

    分析:普通的货币兑换一般都是用floyd。但是本题除了汇率还多出一个条件——手续费,所以不能简单地使用floyd。我用的是spfa求最长路,检查是否有环路。从自己的币种出发,如果发现正环,那么则可以不停地走环路以增加自己手中的价值,又因为所有的路都是双向的,所以当手中的价值增加的足够多之后是一定可以回到自己原有的币种的。又因为正环能使价值达到正无穷,所以回去之后价值一定增加。所以本题转化为判断是否有正环。

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    #define maxm 105
    #define maxn 105
    
    struct Edge
    {
        int v, next;
        double rate, commission;
    }edge[maxm * 2];
    
    int n, m;
    int s;
    int head[maxn];
    double v;
    double dist[maxn];
    bool in_queue[maxn];
    int push_cnt[maxn];
    int q[maxn];
    int edge_cnt;
    
    void addedge(int a, int b, double r, double c)
    {
        edge[edge_cnt].v = b;
        edge[edge_cnt].next = head[a];
        edge[edge_cnt].rate = r;
        edge[edge_cnt].commission = c;
        head[a] = edge_cnt++;
    }
    
    void input()
    {
        edge_cnt = 0;
        memset(head, -1, sizeof(head));
        scanf("%d%d%d%lf", &n, &m, &s, &v);
        s--;
        for (int i = 0; i < m; i++)
        {
            int a, b;
            double r, c;
            scanf("%d%d", &a, &b);
            a--;
            b--;
            scanf("%lf%lf", &r, &c);
            addedge(a, b, r, c);
            scanf("%lf%lf", &r, &c);
            addedge(b, a, r, c);
        }
    }
    
    bool spfa(int s)
    {
        for (int i = 0; i < n; i++)
            dist[i] = -1;
        dist[s] = v;
        memset(in_queue, 0, sizeof(in_queue));
        memset(push_cnt, 0, sizeof(push_cnt));
        int front, rear;
        front = 0;
        rear = 0;
        q[rear++] = s;
        in_queue[s] = true;
        push_cnt[s] = 1;
        
        while (front != rear)
        {
            int u = q[front++];
            if (front == maxn)
                front = 0;
            in_queue[u] = false;
            double cur = dist[u];
            for (int i = head[u]; ~i; i = edge[i].next)
            {
                int v = edge[i].v;
                double r = edge[i].rate;
                double c = edge[i].commission;
                double temp = (cur - c) * r;
                if (temp > dist[v])
                {
                    dist[v] = temp;
                    //printf("%d %.2f
    ", v, dist[v]);
                    if (in_queue[v])
                        continue;
                    q[rear++] = v;
                    if (rear == maxn)
                        rear = 0;
                    in_queue[v] = true;
                    push_cnt[v]++;
                    if (push_cnt[v] > n)
                        return true;
                }
            }
            if (dist[s] > v)
                return true;
        }        
        return false;
    }
    
    int main()
    {
        //freopen("t.txt", "r", stdin);
        input();
        if (spfa(s))
            puts("YES");
        else
            puts("NO");
        return 0;
    }
    View Code
  • 相关阅读:
    Flutter 容器(4)
    Linux 安装maven环境
    ajaxStart、ajaxStop使用注意事项
    jquery里用正则来验证密码,必须包含大小写字母,数字及特殊符号,或最少包含两种
    Nginx 相关介绍(Nginx是什么?能干嘛?配有图片示例)
    常见web攻击总结
    用php的chr和ord函数实现字符串和ASCII码互转
    消息队列设计精要
    mysql索引总结----mysql 索引类型以及创建
    MySQL事务隔离级别详解
  • 原文地址:https://www.cnblogs.com/baoluqi/p/3745534.html
Copyright © 2011-2022 走看看