第一次做圖論的題,所以如果下面的話有說的不對的還請見諒。
題目概述:
我們的主人公是一個套利商人,通過在各個零錢兌換點來回來去換錢來得到最大的利潤,零錢點的信息有零錢兌換率,手續費。我們只需要判斷最後他手裏的錢是不是能增加就好了。思想就在於算“正權環”。
算法思想:
我們用Bellman-Ford來做這道題,模型化的方法就是每一種貨幣當作圖的一個點,每一種exchange station作爲一條邊,邊要記載着從哪裏,到哪裏,change_rate以及手續費。開一個struct來記載這些信息。然後這樣組成一張圖。
更新每一張圖,d[e[j].to]相當於如果當前change之後所擁有的錢,(d[e[j].from]-e[j].rate)*d[j].com相當於新路之後所擁有的錢,然後比較大小如果大的話就更新。model之後相當於是那個圖的最長路徑。
應該就是一個非常naive的算法,只是我是初學所以不太瞭解,最後真正的代碼和Bellman-Ford的僞代碼都十分相似。
交到OJ之後是140多MS,查題解的時候發現有各種十幾MS的應該就是所謂的SPFA做的吧。
代碼部分:
#include <iostream> using namespace std; struct edge{ int from, to; double rate, com; }; edge e[217]; double d[117]; int n, m,s; double v; int main() { cin >> n >> m >> s >> v; for (int i = 0; i < m * 2; i += 2){ int tmp_from, tmp_to; double tmp_rate, tmp_com; cin >> tmp_from >> tmp_to >> tmp_rate >> tmp_com; e[i].from = tmp_from; e[i].to = tmp_to; e[i].rate = tmp_rate; e[i].com = tmp_com; cin >> tmp_rate >> tmp_com; e[i + 1].from = tmp_to; e[i + 1].to = tmp_from; e[i + 1].rate = tmp_rate; e[i + 1].com = tmp_com; } d[s] = v; //Bellman-ford algorithm for (int i = 0; i < n-1; i++){ for (int j = 0; j < 2 * m; j++){ if (d[e[j].to] < (d[e[j].from] - e[j].com)*e[j].rate) { d[e[j].to] = (d[e[j].from] - e[j].com)*e[j].rate; } } } bool flag = false; for (int j = 0; j < 2 * m; j++){ if (d[e[j].to] < (d[e[j].from] - e[j].com)*e[j].rate) { flag = true; break; } } if (flag) cout << "YES" << endl; else cout << "NO" << endl; return 0; }