sgu 103 Traffic Lights 解题报告及测试数据

103. Traffic Lights

Time limit per test: 0.25 second(s)

Memory limit: 4096 kilobytes

题解:

1、其实就是求两点间的最短路,不过加了交通灯的限制,使得两点间的所需时间并不只是由路程决定。

2、只有一条路两个端点的交通灯颜色相同时,该路才可以通过。但是这有一种情况,当两个交通灯处于不同颜色时,经过t时间,交通灯又恰好处于不同颜色,由于最初有一个颜色预变时间riC以及蓝色tiB、紫色周期tiP ,那么就需要计算交通灯变化时间的函数递归两次(函数执行三次),如果递归两次后还处于不同颜色,那么可以断定该交通灯蓝、紫色周期相反,不能通过。例如B 32 32 13和P 32 96 49 经过32s后变成P 13 32 13 和B 96 96 49(紫色变为蓝色后,将过tiB时间即96变为紫色),那么很显然,此时再过13s即可变为相同颜色。那么这两点所需等待交通灯时间为13+32=45s。一开始只都递归了一次,在test 6的时候挂了,所以计算等待函数,应递归两次。

3、最短路算法,dijkstra算法的复杂度为O(N^2),最后提交的结果是用时31ms。当然求最短路,dfs也是可以的,但是经过尝试,dfs在test 2 就TLE了。

以下是代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include <cstdio>
#include <iostream>
#include <cstring>
#include <climits>
#include <cstdlib>
using  namespace std;
int  st,ed;
int  N,M;
int  c[2][2];          //0 b,1 p;
int  a[310][310];   // 记录输入的无向图
int  Min=INT_MAX;    // 最大值
struct  Light{    // 记录输入的交通灯的信息
     int  c, t,b,p;// c输入的颜色,t变换时间,b,p周期
}L[310];        
void  input(){  // 输入
     int  t1,t2;
     char  str[3];
     scanf ( "%d%d%d%d" ,&st,&ed,&N,&M);
     for ( int  i=1;i<=N;i++){
         scanf ( "%s%d%d%d" ,str,&L[i].t,&L[i].b,&L[i].p);
         L[i].c= str[0] == 'B' ? 0 :1;
     }
     for ( int  i=1;i<=N;i++)
         for ( int  j=1;j<=N;j++)
             if (i!=j)a[i][j]=Min;
     for ( int  i=1;i<=M;i++){
         scanf ( "%d%d" ,&t1,&t2);
         scanf ( "%d" ,&a[t1][t2]);
         a[t2][t1]=a[t1][t2];
     }
}
void  calnow(int v,int pre,int k){ //计算第v个节点在过了pre时间后的颜色
     if (pre<L[v].t){
         c[k][0] = L[v].c;
         c[k][1] = L[v].t-pre;
         return  ;
     }
     int  mo = (pre - L[v].t)%(L[v].b+L[v].p);
     switch (L[v].c){
     case  0 :
         if (mo < L[v].p){
             c[k][0]=1;c[k][1]=L[v].p - mo;
         } else {
             c[k][0]=0;c[k][1]=L[v].b - (mo - L[v].p);
              } break ;
     case  1 :
         if (mo < L[v].b){
             c[k][0]=0;c[k][1]=L[v].b - mo;
         } else {
             c[k][0]=1;c[k][1]=L[v].p - (mo - L[v].b);
              } break ;
     }
}
int  caldelay(int v,int u,int pre,int f){ // 计算如果走v—u需要多长时间
     calnow(v,pre,0);
     calnow(u,pre,1);
     if (c[0][0] == c[1][0]) return  0;
     int  t1 = c[0][1],t2=c[1][1];
     if (t1 == t2){
         if (f==2) return  -1;else {
             int   t = caldelay(v,u,pre+t1,f+1);//递归两次,才能确定能否通行。
             if (t==-1) return  -1;
             return  t+t1;
         }
     }
     return  t1<t2 ? t1:t2;
}
void  dijkstra()// 狄杰斯特拉算法,求最短路
{
     int  v=st;
     int  d[310],pr[310],vis[310];
     memset (vis,0, sizeof (vis));
     memset (pr,0, sizeof (pr));
     for ( int  i=0;i<310;i++)d[i]=Min;
     for ( int  i=1;i<=N;i++)
     if (a[v][i]<Min){
         d[i]=a[v][i]+caldelay(v,i,0,0);
         pr[i]= v;
     } else { d[i]=Min;pr[i]=0;}
     vis[v]=1;pr[v]=0;
     for ( int  i=1;i<=N;i++){
         int  k=0,m=Min;
         for ( int  j=1;j<=N;j++)
             if (!vis[j] && d[j]< m)m = d[k=j];
         if (k==0) break ;
         vis[k]=1;
         for ( int  j=1;j<=N;j++)
         if (k!=j && a[k][j]!=Min){
             int  t = caldelay(k,j,d[k],0);
             if (t==-1) continue ;
             if (d[j]>d[k]+t+a[k][j]){
                 d[j] = d[k]+t+a[k][j];
                 pr[j]=k;
             }
         }
     }
     if (st==ed) printf ( "0\n%d\n" ,st);
     else  if(d[ed]==Min)printf("0\n");
     else {
         printf ( "%d\n" ,d[ed]);
         int  t =ed,path[310],k=0;
         while (pr[t]){ path[++k]=pr[t];t =pr[t];}
         path[0]=ed;
         for ( int  i=k;i>=0;i--)
             printf ( "%d " ,path[i]);
         printf ( "\n" );
     }
}
int  main(){
     //freopen("1.in","r",stdin);
     input();
     dijkstra();
}

以下是测试数据:

sample input

10 2

17 2

B 42 5 96 

B 47 51 60 

B 49 28 70 

B 71 77 17 

P 95 97 59 

B 5 56 99 

B 82 56 74 

P 97 60 15 

P 78 32 54 

B 3 20 55 

B 84 8 46 

P 93 32 64 

B 25 11 99 

B 73 33 15 

B 59 58 70 

P 85 61 61 

P 53 13 43 

6 12 17

15 12 75

 

4 4

13 11

P 79 49 75 

B 87 71 22 

B 11 79 30 

P 91 1 72 

B 50 59 84 

B 88 72 41 

B 85 21 47 

B 66 11 100 

B 39 21 28 

B 42 59 42 

P 4 47 2 

B 41 36 48 

P 97 60 25 

11 3 38

10 10 57

7 6 86

5 9 69

7 9 17

5 9 77

4 10 13

6 3 79

2 8 78

3 12 90

13 9 37

 

4 5

5 20

P 35 52 3 

B 10 82 91 

B 29 81 35 

P 85 62 64 

B 87 27 12 

3 5 39

3 4 98

5 3 19

4 2 4

5 1 36

4 1 94

4 2 12

3 4 41

5 2 90

4 2 2

3 1 71

3 1 33

5 1 94

1 5 67

1 4 65

4 1 54

4 5 16

3 3 22

1 2 19

2 5 76

 

1 3

4 17

B 73 40 10 

P 38 5 50 

B 46 64 69 

P 93 88 94 

1 3 91

3 4 72

2 3 14

4 3 46

3 2 5

2 2 52

2 3 26

1 3 93

1 1 75

4 4 84

4 1 39

2 3 63

3 2 10

4 1 70

1 1 71

2 4 75

1 2 34

sample output

0

 

0

4

 

71

4 2 1 5

 

77

1 2 3

你可能感兴趣的:(测试)