110 likes | 402 Views
IOI’99 TRAFFIC LIGHTS 解题报告. 赵静 09908114 zhaojing@db.pku.edu.cn. Traffic Lights. 某地的交通网由路口和公路构成 两个路口之间最多有一条公路,公路两个方向的行驶时间相同。每个路口有一盏信号灯,有 B/P 两种颜色状态。每盏信号灯以它独有的周期进行颜色交替。 车辆的行驶规则 当且仅当某个时刻一条路两端的信号灯颜色相同时,车辆可以从一端出发驶向另一端。车辆可以在路口等候,路口处等候的车辆没有限制。 任务 给定交通网的结构以及信号灯的初始状态和变化周期,求某两点间最快到达的路径。. Input.
E N D
IOI’99 TRAFFIC LIGHTS解题报告 赵静 09908114 zhaojing@db.pku.edu.cn
Traffic Lights • 某地的交通网由路口和公路构成 • 两个路口之间最多有一条公路,公路两个方向的行驶时间相同。每个路口有一盏信号灯,有B/P两种颜色状态。每盏信号灯以它独有的周期进行颜色交替。 • 车辆的行驶规则 • 当且仅当某个时刻一条路两端的信号灯颜色相同时,车辆可以从一端出发驶向另一端。车辆可以在路口等候,路口处等候的车辆没有限制。 • 任务 • 给定交通网的结构以及信号灯的初始状态和变化周期,求某两点间最快到达的路径。
Input (P, 99, 16, 99) (P, 4, 32, 13) (B, 32, 32, 13) Wait 2 (P, 32, 96, 49) Sample Output (B, 2, 16, 99) (P, 6, 32, 13) 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 4 1 2 Wait 64 40 75 76 77 4 3 (P, 38, 96, 49) (P, 2, 87, 4)
建立模型 • 带权无向图的两点间最短路径 • Dijkstra 算法(动态规划的思想) • 问题的焦点:图随时间发生变化 • 结点状态(color, remain)随时间变化 • 导致实际上的权值发生变化 • W (a, b) = T (a, b) + wait (aCurr, bCurr)
4 4 4 1 1 1 2 2 2 40 40 40 75 75 75 76 76 76 4 4 4 3 3 3 37 37 37 Dijkstra 算法回顾 D[1]=0 D[2]=4 D[1]=0 D[2]=4 D[1]=0 D[2]=4 • 1) 对源点s做标记,从s出发更新所有未标记顶点的D值 • If (!mark[i]&&D[i]>D[s]+w[s][i]) D[i]=D[s]+w[s][i]; • 2) 在未标记的顶点中选择D值最小的点作为源点 • 3) 重复1),2) 直至目标点被选作源点 D[4]=MAX D[3]=40 D[3]=40 D[4]=80 D[3]=40 D[4]=77
确定结点的当前状态 • 已知结点的初始状态(c0, r0)和经过的时间t,求当前状态(c, r)。假设c0 = ‘B’, • 若r0 < t,则c = ‘B’,r = r0 – t • 否则令t’ = (t – r0) % (tb + tp) , • 若t’ < tp,c = ‘P’,r = tp – t’ • 若t’ >= tp,c = ‘B’,r = tb – t’ r t’ r0 tp tp tp tb tb r t’ r0 tp tp tb tb
确定边的当前权值 • 已知两端点的当前状态aCurr和bCurr • W (a, b) = T (a, b) + wait (aCurr, bCurr) • 即行驶时间加等候时间得到实际使用的时间 • 如何计算等候时间? • 简单的想法:时间累加,模拟等待过程,上限是a和b周期的最小公倍数LCM (Ta, Tb)。 • 合理的优化:只需考虑a或b状态转换的时刻 • 真的需要一直计算到LCM (Ta, Tb)吗? • 三次就够了
计算等候时间 • aCurr: (c1, r1, tb1, tp1),bCurr: (c2, r2, tb2, tp2),令c1 = ‘B’,求wait (aCurr, bCurr)。 • 若c1 = c2,wait = 0;否则 • 若r1 <> r2, wait = min{r1, r2},否则 • 若tp1 <> tb2,wait = r1 + min {tp1, tb2},否则 • 若tb1 <> tp2,wait = r1 + tp1 + min {tb1, tp2} • 否则a,b之间的路永远无法行驶
对Dijkstra 算法稍加变化 • 1) 对源点s做标记,根据D[s]计算s的当前状态s’ • 2) 从s出发更新所有未标记顶点的D值。 • i’ = currState (i), t = wait (s’, i’); • If (!mark[i]&&D[i]>D[s]+w[s][i]+t) D[i]=D[s]+w[s][i]+t; • 3) 在未标记的顶点中选择D值最小的点作为源点 • 4) 重复1),2) ,3)直至目标点被选作源点 • 为什么可以这样套用Dijkstra算法?
结论 • 总结一类最短路问题的做法 • 特征:符合最优化原理 • 最短路径的子路径仍是最短路径 • 灵活掌握经典算法 • 化繁为简,抓住题目的本质 • 寻找规律是提高效率的好办法
The End • Thank you for your attention!