这道题主要麻烦在信号的等待上 写着写着容易混乱
基本思想就是Dijkstra
#include <iostream>
#define MAXN 305
#define INF (1 << 28)
int map[MAXN][MAXN];
int dist[MAXN];
int v[MAXN];
int M, N;
struct node
{
int color;
int r;
int t[2];
}p[MAXN];
int state(int k, int t, int &r)
{
if(t < p[k].r)
{
r = p[k].r - t;
return p[k].color;
}
t = (t - p[k].r) % (p[k].t[0] + p[k].t[1]);
//每个点初始信号不通 这里用异或得到下一个状态的颜色
int c = p[k].color ^ 1;
if(p[k].t[c] > t)
{
r = p[k].t[c] - t;
return c;
}
else
{
r = p[k].t[c] + p[k].t[c ^ 1] - t;
return c ^ 1;
}
};
int wait(int from, int to, int t)
{
int r1, r2;
int c1 = state(from, t, r1);
int c2 = state(to, t, r2);
if(c1 == c2)
return 0;
if(r1 != r2)
return r1 < r2 ? r1: r2;
if(p[from].t[c1 ^ 1] < p[to].t[c2 ^ 1])
return r1 + p[from].t[c1 ^ 1];
else if(p[from].t[c1 ^ 1] > p[to].t[c2 ^ 1])
return r2 + p[to].t[c2 ^ 1];
else
return -1;
};
int Dij(int start, int end)
{
for(int i = 1; i <= N; i++)
{
dist[i] = INF;
v[i] = false;
}
dist[start] = 0;
int k;
int f = -1;
while(f != INF)
{
f = INF;
for(int i = 1; i <= N; i++)
{
if(!v[i] && dist[i] < f)
{
f = dist[i];
k = i;
}
}
v[k] = true;
for(int i = 1; i <= N; i++)
{
int tm = wait(k, i, dist[k]);
if(tm == -1)
continue;
if(!v[i] && map[k][i] && dist[i] > tm + dist[k] + map[k][i])
{
dist[i] = tm + dist[k] + map[k][i];
}
}
}
return dist[end] >= INF ? 0: dist[end];
};
int main()
{
int start, end;
std::cin >> start >> end;
std::cin >> N >> M;
int i = 1;
char sig;
while(i <= N)
{
std::cin >> sig >> p[i].r >> p[i].t[0] >> p[i].t[1];
if(sig == 'B')
p[i].color = 0;
else
p[i].color = 1;
i++;
}
i = 1;
int u, v, dur;
memset(map, 0, sizeof(map));
while(i <= M)
{
std::cin >> u >> v >> dur;
map[u][v] = map[v][u] = dur;
i++;
}
int res = Dij(start, end);
std::cout << res << "\n";
return 0;
}