SGU 103 Traffic Lights 翻译 题解
每个测试点:0.5s
内存限制:4096KB
在Dingilville市城市交通的安排很不寻常,公路连接着路口,在两个不同的路口之间最多有一条公路连接,没有公路会连接一个路口自身。正反向通过一条道路的时间是相同的,在每一个路口都有一个交通灯,在任意时刻它要么是蓝色的要么是紫色的,这些灯的颜色是定期交换的:蓝色持续一段时间,紫色持续一段时间。当一条公路两边的交通灯颜色相同时才允许汽车离开一个路口去另一个路口。如果一辆车到达一个路口时的瞬间交通灯的颜色改变了,那就需要重新考虑新的颜色。车辆允许在一个路口进行等待。你将得到关于城市的下列信息:
- 每条公路通过所需要的时间(整数)
- 每一个路口两种交通灯的颜色的持续时间(整数)
- 和每个路口的交通灯的初始颜色和持续时间(整数)
你的任务就是寻找一辆车从给定起始路口到给定终止路口所需要的最短时间。如果这样的路径不止一个,你只能输出其中的一个。
输入:
第一行包括两个数字:起始路口和终止路口。
第二行包含两个数字:n和m。
接下来的n行包含n个路口的信息:第(i+2)行给出了第i个路口的信息:Ci, riC, tiB, tiP。C就是第i个路口的交通灯的初始颜色,要么是B(蓝色)或者P(紫色)。
最后接下来的m行包含m条公路的信息,每行都有:
i, j, lij。路口i到路口j由这条公路连接。
2 ≤ N ≤ 300,N代表路口的个数,公路由1~N的整数来标识。 1 ≤ M ≤ 14000,M代表公路的个数。 1 ≤ lij ≤ 100 从路口i到达路口j所需的时间。
2011年6月5日 21时41分50秒---暂时还没翻译完,剩下的明天继续把。
1 ≤ tiC ≤ 100,
tiC代表第i个路口C颜色的交通灯的持续时间,C只能是'B'或者'P'。
1 ≤ riC ≤ tiC,
riC是i路口的交通灯初始颜色c的持续时间。
输出:
如果存在这样一条路径:
- 第一行输出从 起始路口到给定终止路口所需要的最短时间。
- 第二行输出你找到的路径,从起始路口出发到 终止路口。
如果这样的路径不存在:
- 输出0。
样例:
输入 |
输出 |
1 4 4 5 B 2 16 99 P 6 32 13 P 2 87 4 P 38 96 49 1 2 4 1 3 40 2 3 75 2 4 76 3 4 77 |
127 1 2 4 |
================================华丽的分割线 ================================
严重鄙视自己,很明显需要独立一个wait(x, y, t)函数作为子函数,在路口x通往路口y时所需要等待交通灯变得相同的时间,如果不需要等待则为0;需要不可能相同则为∞,但是想了好久没想到wait函数该怎么写,到网上搜了一下,具体看代码里的实现吧,然后就可以转化成为一个单元最短路径了。再鄙视一次自己,找了好久一个问题不知道错在哪里,第6个数据,最后发现竟然是当无法到达的时候我输出的不是0而是我定义的INF,对自己死心了,提交了6次!!!
推荐一个人的题解(后面是时空复杂度引用他的):
http://hi.baidu.com/yali79/blog/item/7308f562342361dae7113a8c.html
时空复杂度
时间
O(C*N2) --Dijkstra C是计算wait函数的重复次数,可看做4
O(C*K*M) --SPFA K是SPFA算法的时间系数,可以看做1
空间
O(N2) --临接矩阵
O(N+M) --临接表/前向星/十字链表
我的代码:
#include <stdio.h>
#include <stdlib.h>
#define INF 0XFFFFFFF
struct node{
int c, r;
int t[2];
}node[301];
int map[301][301];
int s, t;
int m, n;
int dis[301];
int used[301];
int from[301];
int min(int a, int b)
{
return a < b ? a : b;
}
int getcolor(int i, int k, int *t)
{
int x;
if(k < node[i].r){
*t = node[i].r - k;
return node[i].c;
}
x = k - node[i].r;
x %= node[i].t[0] + node[i].t[1];
if(x < node[i].t[1]){
*t = node[i].t[1] - x;
return 1 - node[i].c;
}else{
*t = node[i].t[1] + node[i].t[0] - x;
return node[i].c;
}
}
int wait(int a, int b, int k)
{
int i;
int t = 0;
int x, y;
for(i = 1; i <= 3; i++){
if(getcolor(a, k, &x) == getcolor(b, k, &y)){
return t;
}
k += min(x, y);
t += min(x, y);
}
return INF;
}
int srch(int s)
{
int i, j;
int a, b;
for(i = 1; i <= n; i++){
dis[i] = INF;
}
dis[s] = 0;
for(j = 1; j < n; j++){
b = INF;
for(i = 1; i <= n; i++){
if(!used[i] && dis[i] < b){
s = i;
b = dis[i];
}
}
if(s == t){
break;
}
used[s] = 1;
for(i = 1; i <= n; i++){
if(!used[i] && map[s][i]){
a = wait(i, s, dis[s]);
if(dis[i] > dis[s] + map[s][i] + a){
dis[i] = dis[s] + map[s][i] + a;
from[i] = s;
}
}
}
}
return dis[t];
}
void output(int t)
{
if(t == s){
printf("%d", t);
return;
}
output(from[t]);
printf(" %d", t);
}
int main(int argc, char **argv)
{
int i;
int a, b;
scanf("%d%d", &s, &t);
scanf("%d%d\n", &n, &m);
for(i = 1; i <= n; i++){
a = 0;
scanf("%c%d", (char *)&a, &node[i].r);
if(a == 'B'){
node[i].c = 0;
scanf("%d%d\n", &node[i].t[0], &node[i].t[1]);
}else{
node[i].c = 1;
scanf("%d%d\n", &node[i].t[1], &node[i].t[0]);
}
}
for(i = 0; i < m; i++){
scanf("%d%d", &a, &b);
scanf("%d", &map[a][b]);
map[b][a] = map[a][b];
}
a = srch(s);
if(a == INF){
printf("0\n");
}else{
printf("%d\n", a);
output(t);
printf("\n");
}
return 0;
}