比较简单的一道题目,考察逆推法,从终点逆推到起始点即可,注意要存储每条边的信息,对应的每个顶点要考虑所有的发车时间以及利用概率计算相应的期望值即可,具体实现见如下代码:
#include<iostream>
#include<vector>
#include<string>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<algorithm>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<sstream>
#include<cstdio>
#include<deque>
#include<functional>
using namespace std;
const int N = 2100;
const double Inf = 10000000000000.00;
const double ex = 1e-10;
double cost[N][60];
vector<double> test;
class Road{
public:
int from, to, start, dur, per, delay;
};
class Solve{
public:
map<string, int> record;
int amount;
string starts, ends;
int total;
vector<int> G[N];
vector<Road> road;
bool visit[N];
int s_ind, e_ind;
int find_location(string s){
if (record.find(s) != record.end()) return record[s];
record[s] = amount;
return amount++;
}
bool update(int ide){
bool flag = false;
int from = road[ide].from;
int to = road[ide].to;
for (int i = 0; i < 60; i++){
double wait = (road[ide].start - i + 60) % 60;
double total_cost = (1.0 - road[ide].per / 100.0)*(road[ide].dur
+cost[to][(road[ide].start+road[ide].dur)%60]);
for (int j = 1; j <= road[ide].delay; j++)
total_cost += 1.0*road[ide].per / 100.0 / road[ide].delay*
(road[ide].dur + j+cost[to][(road[ide].start+j+road[ide].dur)%60]);
if (total_cost+wait < cost[from][i]-ex){
cost[from][i] = total_cost+wait;
flag = true;
}
}
return flag;
}
void getRes(){
queue<int> q;
q.push(e_ind);
visit[e_ind] = true;
for (int j = 0; j < 60; j++)
cost[e_ind][j] = 0;
while (!q.empty()){
int id = q.front();
q.pop();
for (int i = 0; i < G[id].size(); i++){
int ide = G[id][i];
int f = road[ide].from;
if (update(ide) && !visit[f]){
q.push(f);
visit[f] = true;
}
}
visit[id] = false;
}
double ans = Inf;
for (int i = 0; i < 60; i++)
ans = min(ans, cost[s_ind][i]);
if (ans >= Inf) cout << "IMPOSSIBLE\n";
else cout <<setprecision(10)<< ans << endl;
}
void Init(){
amount = 0;
for (int i = 0; i < N; i++){
for (int j = 0; j < 60; j++) cost[i][j] = Inf;
}
record.clear();
road.clear();
memset(visit,0,sizeof(visit));
cin >> starts >> ends;
for (int i = 0; i < N; i++) G[i].clear();
s_ind = find_location(starts);
e_ind = find_location(ends);
cin >> total;
for (int i = 0; i < total; i++){
string a, b;
cin >> a >> b;
int a_ind = find_location(a), b_ind = find_location(b);
Road temp;
temp.from = a_ind, temp.to = b_ind;
cin >> temp.start >> temp.dur >> temp.per >> temp.delay;
road.push_back(temp);
G[b_ind].push_back(road.size()-1);
}
}
void Deal(){
Init();
getRes();
}
};
int main(){
int Case;
cin >> Case;
Solve a;
while (Case--){
a.Deal();
}
return 0;
}