HDOJ 1217 Arbitrage

题意:已知有N种货币以及兑换税率,求是否存在一种兑换方法使钱越来越多。

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1217

思路:最短路问题,将加法换成乘法,不能使用dij算法,注意这里不能用Dijkstra,因为乘法中小于1相当于加法中的小于0,会形成负环导致WA。

注意点:可能出现起点与终点是同一点的路径(WA了一次)


以下为AC代码:

Run IDSubmit TimeJudge StatusPro.IDExe.TimeExe.MemoryCode Len.LanguageAuthor
119022812014-10-18 14:50:28Accepted1217265MS412K5545 BG++luminous11

//SPFA
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <deque>
#include <list>
#include <cctype>
#include <algorithm>
#include <climits>
#include <queue>
#include <stack>
#include <cmath>
#include <set>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

struct node
{
    string a;
    string b;
    double tran;
} tmp;


double adj[50][50];
double path[50];
int cnt[50];
int t;
int ke;
bool flag;
string str[30];

void init ()
{
    memset ( path, 0, sizeof( path ) );
    memset ( cnt, 0, sizeof ( cnt ) );
    memset ( adj, 0, sizeof ( cnt ) );
    flag = false;
}

void SPFA ( int be, int en )
{
    queue<double>p;
    p.push( be );
    for ( int i = 0; i < t; i ++ )
    {
        if ( adj[be][i] != 0 )
        {
            path[i] = adj[be][i];
            break;
        }
    }
    while ( ! p.empty() )
    {
        be = p.front();
        p.pop();
        for ( int i = 0; i < t; i ++ )
        {
            if ( path[i] < path[be] * adj[be][i] )
            {
                path[i] = path[be] * adj[be][i];
                p.push( i );
                if ( i == en )
                {
                    if ( path[i] > 1.0 )
                    {
                        flag = 1;
                        return;
                    }
                }
            }
        }
    }
}

int main()
{

    int ncase = 1;
    while ( cin >> t && t )
    {
        init ( );
        for ( int i = 0; i < t; i ++ )
        {
            cin >> str[i];
        }
        int k;
        cin >> k;
        for ( int i = 0; i < k; i ++ )
        {
            int be, en;
            cin >> tmp.a;
            cin >> tmp.tran;
            cin >> tmp.b;
            for ( int j = 0; j < t; j ++ )
            {
                if ( tmp.a == str[j] )
                {
                    be = j;
                }
                if ( tmp.b == str[j] )
                {
                    en = j;
                }
            }
            adj[be][en] = tmp.tran;
            //cout << be << ' ' << en << ' ' << tmp.tran << endl;
        }
        for ( int i = 0; i < t; i ++ )
        {
            SPFA ( i, i );
            if ( flag )
            {
                break;
            }
        }
        if ( flag )
        {
            cout << "Case " << ncase ++ << ": Yes" << endl;
        }
        else
        {
            cout << "Case " << ncase ++ << ": No" << endl;
        }
    }
    return 0;
}


//floyd
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <deque>
#include <list>
#include <cctype>
#include <algorithm>
#include <climits>
#include <queue>
#include <stack>
#include <cmath>
#include <set>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#define INF -10
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

struct node
{
    string a;
    string b;
    double tran;
} tmp;

double adj[50][50];
int t;
string str[30];

void init ()
{
    for ( int i = 0; i < t; i ++ )
    {
        for ( int j = 0; j <t; j ++ )
        {
            adj[i][j] = 0;
        }
    }
    for ( int i = 0; i < t; i ++ )
    {
        adj[i][i] = 1;
    }
}

bool floyd ( )
{
    for ( int i = 0; i < t; i ++ )
    {
        for ( int j = 0; j < t; j ++ )
        {
            for ( int k = 0; k < t; k ++ )
            {
                adj[j][k] = max ( adj[j][k], adj[j][i] * adj[i][k] );
            }
        }
    }
    for ( int i = 0; i < t; i ++ )
    {
        if ( adj[i][i] > 1.0 )
        {
            return 1;
        }
    }
    return 0;
}

int main()
{
    int ncase = 1;
    while ( cin >> t && t )
    {
        init ( );
        for ( int i = 0; i < t; i ++ )
        {
            cin >> str[i];
        }
        int k;
        cin >> k;
        for ( int i = 0; i < k; i ++ )
        {
            int be, en;
            cin >> tmp.a;
            cin >> tmp.tran;
            cin >> tmp.b;
            for ( int j = 0; j < t; j ++ )
            {
                if ( tmp.a == str[j] )
                {
                    be = j;
                }
                if ( tmp.b == str[j] )
                {
                    en = j;
                }
            }
            adj[be][en] = tmp.tran;
        }
        if ( floyd () )
        {
            cout << "Case " << ncase ++ << ": Yes" << endl;
        }
        else
        {
            cout << "Case " << ncase ++ << ": No" << endl;
        }
    }
    return 0;
}

//数据生成器
int main()
{
    freopen ( "data.in", "w", stdout );
    srand((unsigned)time(NULL));
    int k = 0;
    while ( k ++ < 50 )
    {
        int n = rand() % 23 + 3;
        cout << n << endl;
        char ch = 'a';
        char str[30];
        for ( int i = 0; i < n; i ++ )
        {
            str[i] = ch + i;
            cout << str[i] << endl;
        }
        int k = rand() % ( n * ( n - 1 ) );
        cout << k << endl;
        for ( int i = 0; i < k; i ++ )
        {
            cout << str[rand () % n] << ' ';
            cout << rand () % 100 << '.' << rand() % 99 + 1 << ' ';
            cout << str[rand () % n];
            cout << endl;
        }
    }

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值