1. 程式人生 > >poj 1860 -- Currency Exchange(Bellman-Ford)

poj 1860 -- Currency Exchange(Bellman-Ford)

ase 類型 操作 ring itl 完成 title 循環 sta

poj 1860 -- Currency Exchange(Bellman-Ford)

題意:

我們的城市有幾個貨幣兌換點。讓我們假設每一個點都只能兌換專門的兩種貨幣。可以有幾個點,專門從事相同貨幣兌換。每個點都有自己的匯率,外匯匯率的A到B是B的數量你1A。同時各交換點有一些傭金,你要為你的交換操作的總和。在來源貨幣中總是收取傭金。

例如,如果你想換100美元到俄羅斯盧布兌換點,那裏的匯率是29.75,而傭金是0.39,你會得到(100 - 0.39)×29.75=2963.3975盧布。

你肯定知道在我們的城市裏你可以處理不同的貨幣。讓每一種貨幣都用唯一的一個小於N的整數表示。然後每個交換點,可以用6個整數表描述:整數a和b表示兩種貨幣,a到b的匯率,a到b的傭金,b到a的匯率,b到a的傭金。

nick有一些錢在貨幣S,他希望能通過一些操作(在不同的兌換點兌換),增加他的資本。當然,他想在最後手中的錢仍然是S。幫他解答這個難題,看他能不能完成這個願望。

輸入數據:

第一行四個數,N,表示貨幣的總數;M,兌換點的數目;S,nick手上的錢的類型;V,nick手上的錢的數目;1<=S<=N<=100, 1<=M<=100, V 是一個實數 0<=V<=103.

接下來M行,每行六個數,整數a和b表示兩種貨幣,a到b的匯率,a到b的傭金,b到a的匯率,b到a的傭金(0<=傭金<=102,10-2<=匯率<=102

輸出數據:

如果nick能夠實現他的願望,則輸出YES,否則輸出NO。

樣例輸入:

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

樣例輸出

YES

解題思路:

使用Bellman-Ford,與這道題相似的題POJ 2240 -- Arbitrage(Bellman-Ford)

循環一圈之後就與本金比是否增大是不可取的,因為萬一轉為本金的傭金很高,但是存在一個一次增加一點點的正環的話就需要循環很多次才可以高於本金。

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 const int maxm = 105
;// 1<=S<=N<=100, 1<=M<=100, V is real number, 0<=V<=103. 5 struct node{ 6 int ci,cj;//交換點交換的兩種貨幣 7 double cij;//匯率 i->j 8 double mij; //手續費 9 }state[2*maxm]; 10 int n,m;//n為貨幣種類數,m為站點數 11 int type;//Nick手上的貨幣種類 12 double qua;//Nick手上貨幣的價值 13 bool flag; 14 double dist[maxm]; 15 16 bool solve_case(int v0) 17 { 18 flag = false; 19 memset(dist,0,sizeof(dist)); 20 dist[v0] = qua; 21 for(int k=1;k<=n;k++)//進行n次 松弛操作 22 { 23 flag = false; 24 for(int i=0;i<2*m;i++){//判斷每一條有向邊,加入它是否能使得最大距離增加 25 if((dist[state[i].ci]-state[i].mij)*state[i].cij > dist[state[i].cj]) 26 { 27 dist[state[i].cj] = (dist[state[i].ci]-state[i].mij)*state[i].cij; 28 flag = true; 29 } 30 } 31 if(!flag)//已經不再進行松弛 32 break; 33 } 34 //循環一圈之後就與本金比是否增大是不可取的,因為萬一轉為本金的傭金很高, 35 //但是存在一個一次增加一點點的正環的話就需要循環很多次才可以高於本金。 36 //if(dist[v0]>qua) flag = true; 37 38 for(int k=0;k<2*m;k++) 39 if(dist[state[k].cj] < (dist[state[k].ci]-state[k].mij)*state[k].cij ) 40 return true; 41 return false; 42 43 } 44 45 int cin_case() 46 { 47 while(cin>>n){ 48 cin>>m; 49 cin>>type>>qua; 50 for(int i=0;i<2*m;i+=2){//輸入交換點的信息 51 cin>>state[i].ci>>state[i].cj>>state[i].cij>>state[i].mij>>state[i+1].cij>>state[i+1].mij; 52 state[i+1].cj = state[i].ci;state[i+1].ci = state[i].cj; 53 } 54 return 1; 55 } 56 return 0; 57 } 58 59 int main() 60 { 61 while(cin_case()) 62 { 63 if(solve_case(type)) cout<<"YES"<<endl; 64 else cout<<"NO"<<endl; 65 } 66 67 return 0; 68 }

技術分享圖片

poj 1860 -- Currency Exchange(Bellman-Ford)