一道关于环形交通枢纽(大转盘)的模拟题,但是根本与实际情况一点都不相符,反而有诸多难以理解的地方
数据规模不大,直接模拟交通情况计算最后时间即可,因此关键是如何用计算机建模来模拟车辆运行的情况
建模
大转盘可以被抽象为左边的图,外环4个节点叫做entry point,内环4个节点属于roundabout。车辆首先进入entry point,再进入中间的roundabout,按照箭头所示逆时针方向行进,到达对应方向的roundabout point,下一个时刻直接从图中离开。
用(a, b)分别表示内环和外环的节点状态,a[0], a[1], a[2], a[3]分别表示N, W, S, E方向上的节点, b同理
a[i]=0, 1, 2, 3分别表示在对应节点上存在一辆要去往N, W, S, E方向上的车辆; a[i]=4表示没有车, b同理
令seq[i]表示对应方向上的车辆进入entry point的等待队列(车辆不能一下子全部涌入entry point, 当车辆过多只能在图外的队列中排队等候)
初始状态(a, b) = ([4,4,4,4], [4,4,4,4])
规则
有了状态还需要设置系统运行的规则,最重要的是题目中的一句话:
A car decides whether to enter the roundabout based on its knowledge from the previous second
也就是说完全可以根据前一秒的状态推出下一秒的状态。具体规则不详细说了,见代码,要注意几个问题:
- roundabout的点和entry的点要做不同的处理
- 判断4个外环都有节点的锁死状态,在这种情况下北边外环节点移动的情况会变更
- 在所有图中的车辆都移动之后记得将等待队列的车辆加入图,如果可以的话
最后,按照时间来模拟直到所有车辆全部离开为止
吐槽
这道题的各种歧义也真是逗,不看例子几乎都搞不清这个模型是怎么运作的
A car has the right to enter only if there are no cars to its immediate left (either on the roundabout or waiting to get on the roundabout)
大转盘的immediate left是哪边?敢用顺时针方向么?
A roundabout has 4 entry points: from the North, East, South and West; and 4 exit points at the same locations (see Example 0 for a diagram)
自己的图exit points和entry points画重叠了么?那什么叫at the same locations?真不想说那个图了,画的好像以为一个地方可以待两辆车一样:一个进一个出
Cars can enter, leave or move one position on the roundabout. Each of those events requires one second.
如果以上动作都要花一秒的话,请告诉我为什么那个图Time=0的时候就有车了,难道我需要默认进场是瞬间完成的?
请告诉我车辆有可能相撞吗?什么,你说需要我自己去证明:在任何情况下两辆车都不可能相撞,或者不证明直接开始做题。
这道题跟那个vending machine的题真是一个尿性

1 def hasCar(a, b, seqs): 2 for x in a: 3 if x != 4: 4 return True 5 for x in b: 6 if x != 4: 7 return True 8 for seq in seqs: 9 if len(seq) != 0: 10 return True 11 return False 12 13 def rtrim(s): 14 i = len(s) - 1 15 while i >= 0 and s[i] == '-': 16 i = i - 1 17 return s[0:i+1] 18 19 def localfyTimeTable(s): 20 s = rtrim(s) 21 table = [] 22 for ch in s: 23 if ch == 'N': 24 x = 0 25 elif ch == 'W': 26 x = 1 27 elif ch == 'S': 28 x = 2 29 elif ch == 'E': 30 x = 3 31 else: 32 x = 4 33 table.append(x) 34 return table 35 36 def addCar(time, timeTable, seq): 37 for i in range(0, 4): 38 if time < len(timeTable[i]) and timeTable[i][time] != 4: 39 seq[i].append(timeTable[i][time]) 40 41 def cycle(i): 42 return (4+i) % 4 43 44 45 def moveCar(a, b, seq): 46 aa = [4, 4, 4, 4] 47 bb = [4, 4, 4, 4] 48 49 # 移动roundabout里的 50 for i in range(0, 4): 51 if a[i] == 4: 52 continue 53 if a[i] == i: 54 pass 55 else: 56 aa[cycle(i+1)] = a[i] 57 58 # 移动wait point里的 59 for i in range(0, 4): 60 if a[cycle(i-1)] == 4 and b[cycle(i-1)] == 4: 61 aa[i] = b[i] 62 else: 63 bb[i] = b[i] 64 65 # 判断锁死状态 66 if b[0] != 4 and b[1] != 4 and b[2] != 4 and b[3] != 4 and a[3] == 4: 67 aa[0] = b[0] 68 bb[0] = 4 69 70 # seq中的是否能进入wait point 71 for i in range(0, 4): 72 if bb[i] == 4 and len(seq[i]) > 0: 73 bb[i] = seq[i].pop(0) 74 75 return (aa, bb) 76 77 class Roundabout: 78 def clearUpTime(self, north, east, south, west): 79 a = [4, 4, 4, 4] 80 b = [4, 4, 4, 4] 81 timeTable = [] 82 timeTable.append(localfyTimeTable(north)) 83 timeTable.append(localfyTimeTable(west)) 84 timeTable.append(localfyTimeTable(south)) 85 timeTable.append(localfyTimeTable(east)) 86 limit = max(len(timeTable[0]), len(timeTable[1]), len(timeTable[2]), len(timeTable[3])) 87 seq = [[], [], [], []] 88 time = 0 89 while hasCar(a, b, seq) or time < limit: 90 addCar(time, timeTable, seq) 91 (a, b) = moveCar(a, b, seq) 92 time = time + 1 93 94 return max(0, time - 1) 95 96 97 # test 98 o = Roundabout() 99 100 # test case 101 assert(o.clearUpTime('--', '--', 'WE', '-S') == 6) 102 assert(o.clearUpTime('WWW', 'NNN', '---', '---') == 9) 103 assert(o.clearUpTime('SSS', 'WW-', 'N', 'S------') == 13) 104 assert(o.clearUpTime('SSS-', '--W---W', 'WE', '-S') == 14) 105 assert(o.clearUpTime('E', '-N', 'W', '-S') == 5) 106 assert(o.clearUpTime('', '', '', '') == 0) 107 assert(o.clearUpTime('W', '', '--E', '') == 6) 108 assert(o.clearUpTime('ES', 'N', 'E', '') == 9) 109 assert(o.clearUpTime('E', 'SN', '-N', 'S-E') == 12)