题意:在一个大楼里,有编号为0~99的100层楼里,还有n座电梯,任务是从0楼到达第k楼,每个电梯都有一个运行速度,表示到达一个相邻楼层需要的时间,由于每个电梯不一定每层都停留,有时需要从一个电梯换到另一个电梯中。换电梯时间总是一分钟,前提两座电梯能停留在换乘楼层,大楼里只有你一个人,问最少需要的时间?
题解:对于电梯x来说,假如它在第i层停留,把x在i层的出口看作一个顶点记为x*100+i。对于x的下一个停靠站j来说,x*100+i和x*100+j可以连一条边,权值就是这个电梯从i到j层所需要的时间,而对于同样在i层停靠的每个电梯来说,x*100+i到y*100+i也连一条边,权值为60(同层换乘)。建图后,遍历所有的x*100的点u和y*100+k的v,使用dijkstra算法求出所有的u,v最短距离的最小值即为所求结果。
附上代码:
#include<bits/stdc++.h>
#define _for(i,a,b) for( int i=(a); i<(b); ++i)
#define _rep(i,a,b) for( int i=(a); i<=(b); ++i)
using namespace std;
const int MAXN = 5, MAXK = 100, MAXP = MAXN*MAXK;
const int INF = 100000 + 10;
struct Edge{ int from, to, dist; };
struct HeapNode{
int d, u;
bool operator < (const HeapNode& rhs) const { return d > rhs.d; }
};
template<int MAXSIZE>
struct Dijkstra{
int n, m, d[MAXSIZE], p[MAXSIZE];
vector<Edge> edges;
vector<int> G[MAXSIZE];
bool done[MAXSIZE];
void init(int n)
{
this->n = n;
for(int i = 0; i < n; i++) G[i].clear();
edges.clear();
m = 0;
}
void addEdge(int from, int to, int dist)
{
edges.push_back((Edge){from, to, dist});
m = edges.size();
G[from].push_back(m - 1);
}
void dijkstra(int s)
{
priority_queue<HeapNode> Q;
fill_n(d, n, INF);
d[s] = 0;
fill_n(done, n, false);
Q.push((HeapNode){0, s});
while(!Q.empty()) {
HeapNode x = Q.top(); Q.pop();
int u = x.u;
if(done[u]) continue;
done[u] = true;
const vector<int>& adj = G[u];
for(int i = 0; i < adj.size(); i++)
{
Edge& e = edges[adj[i]];
int to = e.to;
if(d[to] > d[u] + e.dist) {
d[to] = d[u] + e.dist;
p[to] = adj[i];
Q.push((HeapNode){d[to], to});
}
}
}
}
};
Dijkstra<MAXP+1> solver;
int n, k, T[MAXN];
vector<int> Level[MAXK];
char buf[512];
int readint() { int x; scanf("%d", &x); return x; }
int solve() {
solver.init(n*MAXK+1);
_for(i, 0, n) T[i] = readint();
fgets(buf,500,stdin);
_for(e, 0, n){
fgets(buf,500,stdin);
stringstream iss(buf);
bool first = true;
int l1, l; // 上一层,当前层
while(iss>>l) {
if(first) first = false;
else {
int v = MAXK*e + l1, v2= MAXK*e + l;
int dist = (l-l1)*T[e];
solver.addEdge(v,v2,dist);
solver.addEdge(v2,v,dist);
// printf("[%d,%d]-%d\n",v, v2, dist);
}
Level[l].push_back(e);
l1 = l;
}
}
_for(i, 0, MAXK) {
vector<int>& li = Level[i];
_for(j, 0, li.size()){
_for(m, j+1, li.size()) {
int e1 = li[j], e2 = li[m], v1 = e1*MAXK+i, v2 = e2*MAXK+i;
solver.addEdge(v1,v2,60);
solver.addEdge(v2,v1,60);
// printf("[%d,%d]-%d\n",v1, v2, 60);
}
}
}
vector<int>& L0 = Level[0];
vector<int>& Lk = Level[k];
if(L0.empty() || Lk.empty()) return INF;
int ans = INF;
for(auto i : L0) {
solver.dijkstra(i * 100);
for(auto j : Lk) ans = min(ans, solver.d[j*100 + k]);
}
return ans;
}
int main(){
while(scanf("%d %d\n", &n, &k) == 2) {
int ans = solve();
if(ans != INF) printf("%d\n", ans);
else puts("IMPOSSIBLE");
}
return 0;
}