Currency Exchange

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 60000/30000K (Java/Other)
Total Submission(s) : 4   Accepted Submission(s) : 2
Problem Description
Several currency exchange points are working in our city. Let us suppose that each point specializes in two particular currencies and performs exchange operations only with these currencies. There can be several points specializing in the same pair of currencies. Each point has its own exchange rates, exchange rate of A to B is the quantity of B you get for 1A. Also each exchange point has some commission, the sum you have to pay for your exchange operation. Commission is always collected in source currency.
For
example, if you want to exchange 100 US Dollars into Russian Rubles at the
exchange point, where the exchange rate is 29.75, and the commission is 0.39 you
will get (100 - 0.39) * 29.75 = 2963.3975RUR.
You surely know that there are
N different currencies you can deal with in our city. Let us assign unique
integer number from 1 to N to each currency. Then each exchange point can be
described with 6 numbers: integer A and B - numbers of currencies it exchanges,
and real RAB, CAB, RBA and CBA -
exchange rates and commissions when exchanging A to B and B to A respectively.

Nick has some money in currency S and wonders if he can somehow, after some
exchange operations, increase his capital. Of course, he wants to have his money
in currency S in the end. Help him to answer this difficult question. Nick must
always have non-negative sum of money while making his operations.
 
Input
The first line of the input contains four numbers: N -
the number of currencies, M - the number of exchange points, S - the number of
currency Nick has and V - the quantity of currency units he has. The following M
lines contain 6 numbers each - the description of the corresponding exchange
point - in specified above order. Numbers are separated by one or more spaces.
1<=S<=N<=100, 1<=M<=100, V is real number,
0<=V<=10<sup>3</sup>. <br>For each point exchange rates
and commissions are real, given with at most two digits after the decimal point,
10<sup>-2</sup><=rate<=10<sup>2</sup>,
0<=commission<=10<sup>2</sup>. <br>Let us call some
sequence of the exchange operations simple if no exchange point is used more
than once in this sequence. You may assume that ratio of the numeric values of
the sums at the end and at the beginning of any simple sequence of the exchange
operations will be less than 10<sup>4</sup>. <br>
 
Output
If Nick can increase his wealth, output YES, in other
case output NO to the output file.
 
Sample Input
3 2 1 20.0
1 2 1.00 1.00 1.00 1.00
2 3 1.10 1.00 1.10 1.00
 
Sample Output
YES
 

题目大意:有多种汇币,汇币之间可以交换,这需要手续费,当你用100A币交换B币时,A到B的汇率是29.75,手续费是0.39,那么你可以得到(100 - 0.39) *      29.75 = 2963.3975 B币。问s币的金额经过交换最终得到的s币金额数能否增加

     货币的交换是可以重复多次的,所以我们需要找出是否存在正权回路,且最后得到的s金额是增加的

     怎么找正权回路呢?(正权回路:在这一回路上,顶点的权值能不断增加即能一直进行松弛)

解题思路:单源最短路径算法,因为题目可能存在负边,所以用Bellman Ford算法,

     原始Bellman Ford可以用来求负环,这题需要改进一下用来求正环

     本题是“求最大路径”,之所以被归类为“求最小路径”是因为本题题恰恰与bellman-Ford算法的松弛条件相反,

     求的是能无限松弛的最大正权路径,但是依然能够利用bellman-Ford的思想去解题。

     因此初始化dis(S)=V   而源点到其他点的距离(权值)初始化为无穷小(0),当s到其他某点的距离能不断变大时,

     说明存在最大路径;如果可以一直变大,说明存在正环。判断是否存在环路,用Bellman-Ford和spfa都可以。

AC代码:

 #include <stdio.h>
#include <string.h>
double dis[];
int n,m,s,ans;
double v;
struct data
{
int x,y;
double r,c;
}num[];
void add(int a,int b,double c,double d)
{
num[ans].x = a;
num[ans].y = b;
num[ans].r = c;
num[ans].c = d;
ans ++;
}
bool Bellman_ford()
{
int i,j;
for (i = ; i <= n; i ++) //此处与Bellman-Ford的处理相反,初始化为源点到各点距离0,到自身的值为原值
dis[i] = ;
dis[s] = v;
bool flag;
for (i = ; i < n; i ++)
{
flag = false; //优化
for (j = ; j < ans; j ++)
if (dis[num[j].y] < (dis[num[j].x]-num[j].c)*num[j].r) //注意是小于号
{
dis[num[j].y] = (dis[num[j].x]-num[j].c)*num[j].r;
flag = true;
}
if (!flag) //如果没有更新,说明不存在正环
return false;
}
for (j = ; j < ans; j ++) //正环能够无限松弛
if (dis[num[j].y] < (dis[num[j].x]-num[j].c)*num[j].r)
return true; //有正环
return false;
}
int main ()
{
int i,j;
int a,b;
double r1,c1,r2,c2;
while (~scanf("%d%d%d%lf",&n,&m,&s,&v))
{
ans = ;
for (i = ; i < m; i ++)
{
scanf("%d%d%lf%lf%lf%lf",&a,&b,&r1,&c1,&r2,&c2);
add(a,b,r1,c1);
add(b,a,r2,c2);
}
if (Bellman_ford())
printf("YES\n");
else
printf("NO\n");
}
return ;
}

SPFA算法:

 #include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
const int N = ;
int n, m, s;
double dis[N], v, rate[N][N], cost[N][N]; bool spfa(int start)
{
bool inq[];
memset(inq, , sizeof(inq));
memset(dis, , sizeof(dis));
dis[start] = v;
queue<int> Q;
Q.push(start);
inq[start] = true;
while(!Q.empty())
{
int x = Q.front();
Q.pop();
inq[x] = false;
for(int i = ; i <= n; i++)
{
if(dis[i] < (dis[x] - cost[x][i]) * rate[x][i])
{
dis[i] = (dis[x] - cost[x][i]) * rate[x][i];
if(dis[start] > v)
return true;
if(!inq[i])
{
Q.push(i);
inq[i] = true;
}
}
}
}
return false;
} int main()
{
int i, j;
while(~scanf("%d%d%d%lf",&n,&m,&s,&v))
{
int a, b;
double rab, rba, cab, cba;
for(i = ; i <= n; i++)
for(j = ; j <= n; j++)
{
if(i == j)
rate[i][j] = ;
else
rate[i][j] = ;
cost[i][j] = ;
}
for(i = ; i < m; i++)
{
scanf("%d%d%lf%lf%lf%lf",&a,&b,&rab,&cab,&rba,&cba);
rate[a][b] = rab;
rate[b][a] = rba;
cost[a][b] = cab;
cost[b][a] = cba;
}
if(spfa(s))
printf("YES\n");
else
printf("NO\n");
}
return ;
}

POJ 1860 Currency Exchange (最短路)的更多相关文章

  1. POJ 1860 Currency Exchange 最短路+负环

    原题链接:http://poj.org/problem?id=1860 Currency Exchange Time Limit: 1000MS   Memory Limit: 30000K Tota ...

  2. POJ 1860 Currency Exchange (最短路)

    Currency Exchange Time Limit:1000MS     Memory Limit:30000KB     64bit IO Format:%I64d & %I64u S ...

  3. poj 1860 Currency Exchange (最短路bellman_ford思想找正权环 最长路)

    感觉最短路好神奇呀,刚开始我都 没想到用最短路 题目:http://poj.org/problem?id=1860 题意:有多种从a到b的汇率,在你汇钱的过程中还需要支付手续费,那么你所得的钱是 mo ...

  4. POJ 1860 Currency Exchange 最短路 难度:0

    http://poj.org/problem?id=1860 #include <cstdio> //#include <queue> //#include <deque ...

  5. 最短路(Bellman_Ford) POJ 1860 Currency Exchange

    题目传送门 /* 最短路(Bellman_Ford):求负环的思路,但是反过来用,即找正环 详细解释:http://blog.csdn.net/lyy289065406/article/details ...

  6. POJ 1860 Currency Exchange / ZOJ 1544 Currency Exchange (最短路径相关,spfa求环)

    POJ 1860 Currency Exchange / ZOJ 1544 Currency Exchange (最短路径相关,spfa求环) Description Several currency ...

  7. POJ 1860 Currency Exchange + 2240 Arbitrage + 3259 Wormholes 解题报告

    三道题都是考察最短路算法的判环.其中1860和2240判断正环,3259判断负环. 难度都不大,可以使用Bellman-ford算法,或者SPFA算法.也有用弗洛伊德算法的,笔者还不会SF-_-…… ...

  8. POJ 1860——Currency Exchange——————【最短路、SPFA判正环】

    Currency Exchange Time Limit:1000MS     Memory Limit:30000KB     64bit IO Format:%I64d & %I64u S ...

  9. POJ 1860 Currency Exchange【bellman_ford判断是否有正环——基础入门】

    链接: http://poj.org/problem?id=1860 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=22010#probl ...

随机推荐

  1. HDU 3533 Escape bfs 难度:1

    http://acm.hdu.edu.cn/showproblem.php?pid=3533 一道普通的bfs,但是由于代码实现出了bug还是拖了很久甚至对拍了 需要注意的是: 1.人不能经过炮台 2 ...

  2. winform按钮和子按钮

    实现目标: 一.两组按钮1和2,其中按钮2有两个子按钮, (1)当选按钮1时,按钮2和其子按钮不选中: (2)选中按钮2或其子按钮3和4时,1不选中 (3)选中按钮2时,默认选中其子按钮3 (4)选中 ...

  3. 在JavaScript 自定义对象来模拟Java中的Map

    直接看代码: //模拟一个Map对象 function Map(){ //声明一个容器 var container={}; //定义一个put方法,向容器中存值 this.put=function(k ...

  4. discuz 系列产品 在ie9下注册成功后不跳转bug处理

    header.htm 把 <meta http-equiv="x-ua-compatible" content="ie=7" /> 改为 <m ...

  5. sqlite3 SQL常用语句

    1. select SELECT LastName,FirstName FROM Persons; SELECT * FROM Persons; 2. where SELECT * FROM Pers ...

  6. string.format

    string.Format("{0:#,0}", c.num), //千分号,有小数就保留2位小数 string.Format("{0:N2}", c.amou ...

  7. SQLite实现Top功能

    SQlite本身没有top功能,无法向TSQL一样下Select top 100 * from tb_table,但SQLite提供了一个Limit关键字用来取得相应行数的资料 具体语法实例:Sele ...

  8. HDU 4622 求解区间字符串中的不同子串的个数

    题目大意: 给定一个长度<2000的串,再给最多可达10000的询问区间,求解区间字符串中的不同子串的个数 这里先考虑求解一整个字符串的所有不同子串的方法 对于后缀自动机来说,我们动态往里添加一 ...

  9. js面向对象(构造函数与继承)

    深入解读JavaScript面向对象编程实践 Mar 9, 2016 面向对象编程是用抽象方式创建基于现实世界模型的一种编程模式,主要包括模块化.多态.和封装几种技术. 对JavaScript而言,其 ...

  10. (转)HTML5开发学习(3):本地存储之Web Sql Database

    原文:http://www.cnblogs.com/xumingxiang/archive/2012/03/25/2416386.html HTML5开发学习(3):本地存储之Web Sql Data ...