Currency Exchange
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 42032 | Accepted: 16144 |
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<=103.
For each point exchange rates and commissions are real, given with at most two digits after the decimal point, 10-2<=rate<=102, 0<=commission<=102.
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 104.
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
- 故事依旧很长,就是说在小镇上有个货币兑换处(类似于银行),每个银行能实现两种货币的兑换,每个银行都有自己的汇率,并且还要手续费。。。
- 兑换公式是:(本金-手续费)*汇率
- 有个叫尼克的人,想通过乱七八糟的货币兑换来增加自己的money,问你能不能实现
- 哪有这种好事,要是能实现,我也不告诉他,我要自己去挣钱,嘻嘻嘻
看了两遍没看出这个题的原型是什么,吃饭的时候灵光一闪,其实每种货币就是一个点,每个银行就是一个可以双向进行的路,其实就是连接在这能交易的两种货币(点)的 环 如果你想赚money,就必须保证这是一个正环,可能一次并不能挣到钱,万一手续费很高呢?但即使它是一个一次只能增加一点点的正环,但通过好多次的轮回,就能赚回本金,这叫积土成山定理
- 那么怎么才能判断正权环呢???今天早上刚做了一个判断负权环的题,其实正负权环的判定也挺类似
-
这是一篇判断负权环的blog
-
同样我在这里用了Floyd和SPFA两个方法,其实都是套板子,啊哈哈哈哈哈哈哈哈哈哈~~~
- 奉上我卑微的暴力枚举Floyd代码先:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int mm=105;
int n,m,s;
double v;
double money[mm],hui[mm][mm],tip[mm][mm];
int floyd(){
double d[mm];//money的备份
for(int i=1;i<=n;i++)
d[i]=money[i];
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if((money[i]-tip[i][j])*hui[i][j]>money[j])//increase
money[j]=(money[i]-tip[i][j])*hui[i][j];
for(int i=1;i<=n;i++)
if(d[i]<money[i])
return 1;//ojbk
return 0;
}
int main()
{
scanf("%d%d%d%lf",&n,&m,&s,&v);
while(m--){
int a,b;
double c,d,e,f;
scanf("%d%d%lf%lf%lf%lf",&a,&b,&c,&d,&e,&f);
hui[a][b]=c; tip[a][b]=d;
hui[b][a]=e; tip[b][a]=f;
}
money[s]=v;
floyd();//不写为什么会错???
if(floyd())printf("YES\n");
else printf("NO\n");
return 0;
}
- 再来一篇高大上的SPFA代码:
#include<cstdio>
#include<string>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int inf=0x3f3f3f3f;
const int mm=111;
int n,m,s;
double v;
int a,b;
double money[mm];//本金
double rab,rba,cab,cba;
int cnt;
int head[mm<<1];
struct node{
int a,b;
double r,c;
int next;
}pp[mm<<1];
void add(int a,int b,double r,double c){
pp[cnt].a=a;
pp[cnt].b=b;
pp[cnt].r=r;
pp[cnt].c=c;
pp[cnt].next=head[a];
head[a]=cnt++;
}
int book[mm];
int num[mm];//加入队列的次数
bool spfa(){
queue<int>q;
q.push(s);
book[s]=1;
num[s]++;
money[s]=v;
while(!q.empty()){
int u=q.front();
q.pop();
book[u]=0;
for(int i=head[u];i!=-1;i=pp[i].next){
int t=pp[i].b;
double temp=(money[u]-pp[i].c)*pp[i].r;
if(temp>money[t]){//涨钱了
money[t]=temp;
if(book[t]==0){
q.push(t);
book[t]=1;
num[t]++;
if(num[t]>n)
return true;
}
}
}
}
return false;
}
void init(){
mem(money,0);
mem(head,-1);
mem(book,0);
mem(num,0);
cnt=0;
}
int main()
{
init(); //不要忘了!!!
cin>>n>>m>>s>>v;
while(m--){
cin>>a>>b>>rab>>cab>>rba>>cba;
add(a,b,rab,cab);
add(b,a,rba,cba);
}
if(spfa())
printf("YES\n");
else
printf("NO\n");
return 0;
}