├── .gitignore ├── CodeCraft-2019 ├── config │ ├── answer.txt │ ├── car.txt │ ├── cross.txt │ ├── presetAnswer.txt │ └── road.txt └── src │ └── CodeCraft-2019.py ├── README.md ├── build_and_run.sh ├── logs └── CodeCraft-2019.log └── result ├── chusai.jpg └── fusai.jpg /.gitignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /CodeCraft-2019/config/cross.txt: -------------------------------------------------------------------------------- 1 | #(id,roadId,roadId,roadId,roadId) 2 | (6, 6039, 6001, -1, 5640) 3 | (22, 5301, 6540, 6627, 6653) 4 | (27, 5266, -1, 5612, 5269) 5 | (48, 6036, 6158, 5731, 5278) 6 | (58, 5906, 5911, 6552, -1) 7 | (99, 5885, 5453, -1, 5608) 8 | (104, 5933, 6539, 5127, 5436) 9 | (105, 6794, 5683, 5130, 6864) 10 | (107, 6939, -1, 6716, 5464) 11 | (111, 6068, 6549, 6687, 6484) 12 | (115, 5481, -1, 6629, 6608) 13 | (120, 5207, 5206, 5519, -1) 14 | (130, 5610, 5469, 5216, 6653) 15 | (141, 5130, 5269, 6188, 6236) 16 | (156, -1, 6947, 6006, 5477) 17 | (171, 5911, 5207, 5326, 5289) 18 | (173, 5795, 5043, -1, 5089) 19 | (174, 5505, 5255, 6081, 6970) 20 | (176, 6510, -1, 6721, 5514) 21 | (179, 6549, 6225, 6047, 5196) 22 | (191, 5831, 6644, 5475, -1) 23 | (199, 5216, 6006, 6119, 6089) 24 | (223, 5535, 5988, 6909, -1) 25 | (224, 6365, -1, 5713, 6433) 26 | (238, 6096, 6742, 5680, 6325) 27 | (264, 5984, 6369, 6234, 5882) 28 | (268, 6796, -1, 6444, 6361) 29 | (277, -1, 6478, 6073, -1) 30 | (303, 5742, 6284, 6329, -1) 31 | (342, 5857, 5846, -1, 6706) 32 | (373, 5921, 5184, 6484, 5175) 33 | (398, 5184, 5792, 5608, 5009) 34 | (413, 5759, 5386, -1, 6583) 35 | (417, -1, -1, 5923, 6794) 36 | (454, 6543, 5306, 5034, 5660) 37 | (456, 5129, 6864, 6805, 5526) 38 | (460, 6472, 5456, -1, 6152) 39 | (463, 5610, -1, 5746, 6531) 40 | (479, 6875, 5714, -1, 6997) 41 | (496, 5436, 6583, -1, 5593) 42 | (506, 6650, 5940, 5133, 5218) 43 | (551, 5988, 5078, 6661, 6830) 44 | (560, -1, 6001, 5218, 5339) 45 | (562, 5742, -1, 5029, 5923) 46 | (569, 5222, 6841, 5076, -1) 47 | (589, -1, 5078, 6722, 5691) 48 | (634, 6661, 6795, 5247, 5278) 49 | (635, 6530, 6387, -1, -1) 50 | (664, 6179, 5892, -1, -1) 51 | (674, 5422, 5680, 5897, -1) 52 | (684, 5459, 6521, 5620, -1) 53 | (693, -1, 6433, 6733, 5940) 54 | (699, 6327, 6830, 5731, -1) 55 | (706, 6875, 6539, 5026, 5984) 56 | (719, 6158, 5116, 5270, 5700) 57 | (740, 6828, 6288, 6568, 6687) 58 | (743, -1, 6810, -1, 6795) 59 | (790, 6510, 5957, 5689, -1) 60 | (841, 5714, 5882, 5306, 5076) 61 | (859, 5846, 6722, 5535, -1) 62 | (868, 6012, 6807, 5133, 6586) 63 | (895, 6234, 6430, -1, 5034) 64 | (932, 6028, 5829, 5593, -1) 65 | (935, 6828, 5196, 5204, 5537) 66 | (970, 5301, 6089, 5464, -1) 67 | (994, 5422, -1, 5745, 6569) 68 | (1009, 5700, 6325, 6569, -1) 69 | (1020, 6028, -1, 6552, 6421) 70 | (1034, -1, 6068, 5009, -1) 71 | (1046, 6188, 6623, 6521, -1) 72 | (1058, 5114, 6719, 5540, 6430) 73 | (1061, 5847, 6531, 5640, -1) 74 | (1069, 5326, 5475, 5000, 5632) 75 | (1085, 6627, 5222, -1, -1) 76 | (1105, 5000, 5822, 6612, 5255) 77 | (1107, 6327, 5745, -1, 6909) 78 | (1110, 5378, 5792, 6508, -1) 79 | (1136, 5540, -1, -1, 6444) 80 | (1159, 5090, 5026, -1, -1) 81 | (1160, 6908, 5808, 5542, -1) 82 | (1161, 6081, 5489, -1, 6719) 83 | (1169, 5386, 5345, 6716, -1) 84 | (1170, 6361, 6892, -1, 6058) 85 | (1172, 6472, 5808, 5507, -1) 86 | (1180, 5713, 6545, 6908, 5905) 87 | (1189, 6421, 5289, 6048, -1) 88 | (1195, 6328, -1, 6219, -1) 89 | (1207, 6048, 5632, 5505, -1) 90 | (1208, 5029, -1, 5266, 5683) 91 | (1218, 5481, 5795, 6450, 5574) 92 | (1239, 5739, -1, 5043, 6608) 93 | (1243, 6805, 6236, 5644, 6054) 94 | (1269, 5709, 6706, -1, 6262) 95 | (1271, 5537, 5658, -1, 5181) 96 | (1279, 5175, 6568, 6284, -1) 97 | (1292, 5860, 6058, 5507, 6545) 98 | (1325, 5897, 5953, 5459, -1) 99 | (1330, -1, 5673, 6755, 5089) 100 | (1344, 5905, 6219, 6586, 6733) 101 | (1353, 6742, 5644, -1, 5953) 102 | (1361, 5116, 6124, 5774, -1) 103 | (1378, 5127, 6997, 6566, 5759) 104 | (1425, 5542, 6152, 6258, 6200) 105 | (1427, -1, 5660, 6796, 5860) 106 | (1428, 6346, 5514, -1, 5831) 107 | (1442, 6721, -1, 5658, 5707) 108 | (1456, 6543, 6365, -1, -1) 109 | (1471, 6047, 5822, 6644, 6689) 110 | (1515, -1, 5453, 6478, 6892) 111 | (1519, 6097, 5791, 6449, -1) 112 | (1525, 6235, -1, -1, 5620) 113 | (1540, 6530, 6258, 6810, 5675) 114 | (1599, 6012, -1, 6450, 6755) 115 | (1610, 6612, 6225, -1, 5489) 116 | (1653, -1, 6650, 6039, 5746) 117 | (1677, 5408, 6262, -1, 5892) 118 | (1686, -1, 5574, 6328, 6200) 119 | (1689, 6575, 6629, 5108, 5408) 120 | (1692, 5129, 6508, 5921, -1) 121 | (1709, 5378, 5774, 6073, 5885) 122 | (1748, -1, 6065, 5247, 5456) 123 | (1758, 6387, 6375, 5709, 5108) 124 | (1764, -1, -1, 5689, 6097) 125 | (1770, 5244, 6054, 6096, 5270) 126 | (1779, 6369, 5090, 6970, 5114) 127 | (1795, 6329, 6288, 5181, -1) 128 | (1803, 5847, -1, 5477, 5469) 129 | (1824, 6179, -1, 5739, 6575) 130 | (1827, 6623, 5612, -1, 6235) 131 | (1852, 5204, 6689, -1, 5707) 132 | (1897, 5957, 6346, 5519, 5791) 133 | (1901, 5675, 5691, 5857, 6375) 134 | (1927, 6119, 5470, -1, 6939) 135 | (1933, 6124, 6036, 6065, -1) 136 | (1953, -1, 6841, 6540, 6502) 137 | (1957, 5829, -1, -1, 5933) 138 | (1968, -1, 6449, 5206, 5906) 139 | (1981, 5345, 6566, 6502, -1) 140 | (1982, 5339, 6807, 5673, -1) 141 | (1984, -1, 5470, 6947, -1) 142 | (1989, -1, 5526, 5244, -1) -------------------------------------------------------------------------------- /CodeCraft-2019/config/road.txt: -------------------------------------------------------------------------------- 1 | #(id,length,speed,channel,from,to,isDuplex) 2 | (5000, 40, 8, 1, 1069, 1105, 1) 3 | (5009, 40, 12, 3, 1034, 398, 1) 4 | (5026, 24, 15, 2, 706, 1159, 1) 5 | (5029, 40, 8, 1, 562, 1208, 1) 6 | (5034, 36, 10, 4, 454, 895, 1) 7 | (5043, 30, 10, 2, 173, 1239, 1) 8 | (5076, 30, 10, 2, 569, 841, 1) 9 | (5078, 40, 8, 3, 589, 551, 1) 10 | (5089, 30, 15, 4, 1330, 173, 1) 11 | (5090, 36, 10, 4, 1159, 1779, 1) 12 | (5108, 40, 15, 3, 1689, 1758, 1) 13 | (5114, 36, 15, 3, 1779, 1058, 1) 14 | (5116, 20, 8, 3, 1361, 719, 1) 15 | (5127, 40, 12, 1, 1378, 104, 0) 16 | (5129, 20, 12, 3, 1692, 456, 1) 17 | (5130, 36, 10, 1, 105, 141, 1) 18 | (5133, 20, 10, 4, 506, 868, 1) 19 | (5175, 20, 8, 2, 373, 1279, 1) 20 | (5181, 20, 10, 4, 1271, 1795, 1) 21 | (5184, 20, 15, 4, 398, 373, 1) 22 | (5196, 24, 15, 4, 179, 935, 0) 23 | (5204, 40, 12, 1, 1852, 935, 1) 24 | (5206, 30, 10, 2, 1968, 120, 1) 25 | (5207, 30, 15, 1, 171, 120, 1) 26 | (5216, 36, 10, 4, 199, 130, 1) 27 | (5218, 36, 12, 2, 560, 506, 1) 28 | (5222, 24, 8, 2, 1085, 569, 1) 29 | (5244, 20, 12, 1, 1989, 1770, 1) 30 | (5247, 20, 8, 2, 1748, 634, 1) 31 | (5255, 36, 8, 3, 174, 1105, 0) 32 | (5266, 24, 15, 1, 1208, 27, 1) 33 | (5269, 20, 10, 2, 141, 27, 1) 34 | (5270, 20, 10, 1, 719, 1770, 1) 35 | (5278, 24, 12, 2, 634, 48, 1) 36 | (5289, 20, 12, 1, 1189, 171, 1) 37 | (5301, 36, 12, 4, 970, 22, 1) 38 | (5306, 24, 10, 1, 841, 454, 1) 39 | (5326, 24, 12, 3, 171, 1069, 0) 40 | (5339, 20, 10, 1, 560, 1982, 1) 41 | (5345, 20, 15, 3, 1169, 1981, 1) 42 | (5378, 20, 12, 3, 1709, 1110, 1) 43 | (5386, 20, 10, 1, 1169, 413, 1) 44 | (5408, 24, 10, 4, 1689, 1677, 1) 45 | (5422, 30, 15, 4, 994, 674, 1) 46 | (5436, 30, 12, 1, 496, 104, 1) 47 | (5453, 24, 12, 4, 1515, 99, 1) 48 | (5456, 36, 10, 1, 460, 1748, 1) 49 | (5459, 36, 8, 4, 1325, 684, 1) 50 | (5464, 30, 8, 1, 107, 970, 1) 51 | (5469, 20, 8, 1, 1803, 130, 1) 52 | (5470, 30, 10, 3, 1984, 1927, 1) 53 | (5475, 24, 8, 2, 1069, 191, 1) 54 | (5477, 30, 10, 1, 156, 1803, 1) 55 | (5481, 36, 15, 4, 1218, 115, 1) 56 | (5489, 20, 10, 4, 1161, 1610, 1) 57 | (5505, 20, 15, 1, 1207, 174, 1) 58 | (5507, 24, 12, 2, 1292, 1172, 1) 59 | (5514, 30, 12, 3, 1428, 176, 1) 60 | (5519, 36, 12, 1, 120, 1897, 1) 61 | (5526, 20, 10, 4, 1989, 456, 1) 62 | (5535, 40, 8, 1, 859, 223, 1) 63 | (5537, 40, 15, 2, 935, 1271, 1) 64 | (5540, 40, 15, 1, 1058, 1136, 1) 65 | (5542, 20, 10, 2, 1160, 1425, 1) 66 | (5574, 40, 8, 4, 1218, 1686, 1) 67 | (5593, 30, 8, 4, 496, 932, 1) 68 | (5608, 24, 8, 1, 99, 398, 1) 69 | (5610, 40, 12, 1, 130, 463, 1) 70 | (5612, 24, 8, 4, 27, 1827, 1) 71 | (5620, 40, 10, 1, 684, 1525, 1) 72 | (5632, 30, 12, 4, 1207, 1069, 1) 73 | (5640, 30, 15, 1, 1061, 6, 1) 74 | (5644, 40, 8, 2, 1243, 1353, 1) 75 | (5658, 30, 10, 4, 1442, 1271, 1) 76 | (5660, 24, 15, 3, 454, 1427, 1) 77 | (5673, 30, 12, 1, 1982, 1330, 1) 78 | (5675, 40, 8, 4, 1540, 1901, 0) 79 | (5680, 20, 12, 3, 238, 674, 1) 80 | (5683, 36, 10, 1, 105, 1208, 1) 81 | (5689, 20, 10, 3, 1764, 790, 1) 82 | (5691, 30, 10, 3, 1901, 589, 1) 83 | (5700, 40, 15, 1, 719, 1009, 1) 84 | (5707, 20, 15, 3, 1852, 1442, 1) 85 | (5709, 40, 12, 1, 1758, 1269, 1) 86 | (5713, 20, 10, 1, 224, 1180, 1) 87 | (5714, 40, 10, 3, 479, 841, 0) 88 | (5731, 30, 15, 1, 48, 699, 1) 89 | (5739, 30, 12, 2, 1239, 1824, 1) 90 | (5742, 36, 15, 3, 303, 562, 1) 91 | (5745, 40, 15, 3, 1107, 994, 1) 92 | (5746, 36, 15, 4, 463, 1653, 1) 93 | (5759, 36, 10, 3, 413, 1378, 1) 94 | (5774, 36, 12, 1, 1709, 1361, 1) 95 | (5791, 36, 8, 4, 1519, 1897, 1) 96 | (5792, 24, 10, 2, 398, 1110, 0) 97 | (5795, 36, 8, 4, 173, 1218, 1) 98 | (5808, 40, 8, 2, 1160, 1172, 1) 99 | (5822, 40, 15, 4, 1105, 1471, 1) 100 | (5829, 20, 10, 3, 932, 1957, 1) 101 | (5831, 40, 12, 1, 191, 1428, 1) 102 | (5846, 40, 8, 2, 342, 859, 1) 103 | (5847, 24, 8, 2, 1803, 1061, 1) 104 | (5857, 24, 8, 1, 1901, 342, 1) 105 | (5860, 36, 12, 2, 1427, 1292, 1) 106 | (5882, 30, 12, 1, 841, 264, 1) 107 | (5885, 24, 8, 3, 99, 1709, 1) 108 | (5892, 30, 8, 2, 664, 1677, 1) 109 | (5897, 36, 15, 1, 674, 1325, 1) 110 | (5905, 24, 12, 1, 1344, 1180, 0) 111 | (5906, 40, 12, 4, 58, 1968, 1) 112 | (5911, 36, 8, 1, 58, 171, 1) 113 | (5921, 24, 8, 3, 373, 1692, 1) 114 | (5923, 20, 12, 4, 417, 562, 1) 115 | (5933, 20, 10, 3, 104, 1957, 1) 116 | (5940, 40, 15, 3, 506, 693, 1) 117 | (5953, 20, 10, 3, 1353, 1325, 1) 118 | (5957, 20, 10, 3, 1897, 790, 1) 119 | (5984, 40, 12, 2, 706, 264, 1) 120 | (5988, 40, 10, 3, 551, 223, 1) 121 | (6001, 20, 15, 4, 6, 560, 1) 122 | (6006, 24, 10, 3, 156, 199, 1) 123 | (6012, 20, 15, 3, 868, 1599, 1) 124 | (6028, 24, 8, 1, 932, 1020, 1) 125 | (6036, 36, 12, 4, 1933, 48, 1) 126 | (6039, 30, 15, 1, 6, 1653, 1) 127 | (6047, 36, 12, 3, 1471, 179, 1) 128 | (6048, 30, 8, 3, 1189, 1207, 1) 129 | (6054, 20, 15, 1, 1770, 1243, 0) 130 | (6058, 24, 12, 4, 1292, 1170, 1) 131 | (6065, 20, 10, 4, 1748, 1933, 1) 132 | (6068, 24, 12, 1, 1034, 111, 1) 133 | (6073, 30, 10, 3, 277, 1709, 1) 134 | (6081, 24, 12, 3, 174, 1161, 1) 135 | (6089, 40, 8, 4, 199, 970, 1) 136 | (6096, 40, 15, 3, 1770, 238, 1) 137 | (6097, 30, 8, 2, 1519, 1764, 1) 138 | (6119, 30, 10, 4, 1927, 199, 1) 139 | (6124, 30, 10, 1, 1933, 1361, 1) 140 | (6152, 30, 12, 2, 1425, 460, 1) 141 | (6158, 36, 15, 1, 48, 719, 0) 142 | (6179, 20, 12, 2, 1824, 664, 1) 143 | (6188, 24, 8, 3, 141, 1046, 1) 144 | (6200, 20, 12, 4, 1686, 1425, 1) 145 | (6219, 40, 8, 1, 1344, 1195, 1) 146 | (6225, 36, 15, 2, 1610, 179, 1) 147 | (6234, 36, 8, 2, 264, 895, 1) 148 | (6235, 36, 12, 3, 1827, 1525, 1) 149 | (6236, 30, 8, 3, 1243, 141, 1) 150 | (6258, 40, 15, 1, 1425, 1540, 1) 151 | (6262, 40, 10, 1, 1677, 1269, 1) 152 | (6284, 20, 10, 4, 1279, 303, 1) 153 | (6288, 20, 12, 3, 740, 1795, 1) 154 | (6325, 24, 12, 2, 1009, 238, 1) 155 | (6327, 20, 8, 1, 699, 1107, 1) 156 | (6328, 36, 10, 1, 1195, 1686, 1) 157 | (6329, 36, 8, 1, 1795, 303, 1) 158 | (6346, 36, 8, 3, 1897, 1428, 1) 159 | (6361, 30, 8, 2, 268, 1170, 1) 160 | (6365, 30, 12, 2, 1456, 224, 1) 161 | (6369, 24, 10, 2, 264, 1779, 0) 162 | (6375, 36, 15, 1, 1758, 1901, 1) 163 | (6387, 40, 10, 3, 635, 1758, 1) 164 | (6421, 36, 10, 1, 1020, 1189, 1) 165 | (6430, 20, 8, 3, 895, 1058, 1) 166 | (6433, 30, 12, 3, 693, 224, 1) 167 | (6444, 24, 15, 3, 268, 1136, 1) 168 | (6449, 40, 12, 2, 1968, 1519, 1) 169 | (6450, 20, 10, 3, 1599, 1218, 1) 170 | (6472, 20, 10, 2, 1172, 460, 1) 171 | (6478, 36, 15, 4, 1515, 277, 1) 172 | (6484, 20, 15, 3, 111, 373, 1) 173 | (6502, 20, 15, 1, 1981, 1953, 1) 174 | (6508, 40, 12, 2, 1110, 1692, 1) 175 | (6510, 30, 10, 4, 790, 176, 1) 176 | (6521, 30, 8, 4, 1046, 684, 1) 177 | (6530, 40, 10, 4, 635, 1540, 1) 178 | (6531, 36, 10, 4, 1061, 463, 1) 179 | (6539, 30, 12, 3, 104, 706, 1) 180 | (6540, 40, 10, 1, 22, 1953, 1) 181 | (6543, 30, 8, 2, 1456, 454, 1) 182 | (6545, 36, 8, 2, 1180, 1292, 1) 183 | (6549, 30, 8, 2, 179, 111, 1) 184 | (6552, 40, 15, 4, 1020, 58, 1) 185 | (6566, 20, 10, 2, 1981, 1378, 1) 186 | (6568, 24, 8, 2, 740, 1279, 1) 187 | (6569, 30, 12, 4, 1009, 994, 1) 188 | (6575, 24, 15, 1, 1824, 1689, 1) 189 | (6583, 24, 10, 3, 413, 496, 1) 190 | (6586, 24, 15, 3, 868, 1344, 1) 191 | (6608, 20, 10, 1, 1239, 115, 1) 192 | (6612, 40, 12, 1, 1105, 1610, 1) 193 | (6623, 40, 8, 2, 1046, 1827, 1) 194 | (6627, 40, 15, 2, 22, 1085, 1) 195 | (6629, 20, 12, 4, 115, 1689, 1) 196 | (6644, 36, 10, 4, 191, 1471, 1) 197 | (6650, 36, 15, 1, 1653, 506, 1) 198 | (6653, 30, 15, 3, 130, 22, 1) 199 | (6661, 24, 10, 4, 634, 551, 0) 200 | (6687, 36, 8, 4, 111, 740, 1) 201 | (6689, 40, 12, 2, 1471, 1852, 1) 202 | (6706, 30, 15, 3, 1269, 342, 1) 203 | (6716, 20, 12, 2, 107, 1169, 1) 204 | (6719, 36, 10, 4, 1058, 1161, 1) 205 | (6721, 40, 15, 3, 176, 1442, 1) 206 | (6722, 20, 8, 1, 589, 859, 1) 207 | (6733, 40, 15, 3, 693, 1344, 1) 208 | (6742, 40, 8, 2, 238, 1353, 1) 209 | (6755, 36, 15, 3, 1330, 1599, 1) 210 | (6794, 20, 12, 1, 417, 105, 1) 211 | (6795, 24, 8, 4, 743, 634, 1) 212 | (6796, 24, 12, 2, 1427, 268, 1) 213 | (6805, 30, 12, 3, 456, 1243, 1) 214 | (6807, 40, 10, 1, 1982, 868, 1) 215 | (6810, 36, 12, 1, 1540, 743, 1) 216 | (6828, 20, 10, 2, 935, 740, 1) 217 | (6830, 40, 8, 4, 551, 699, 1) 218 | (6841, 40, 12, 2, 1953, 569, 1) 219 | (6864, 40, 12, 1, 456, 105, 0) 220 | (6875, 20, 10, 3, 479, 706, 1) 221 | (6892, 30, 10, 1, 1170, 1515, 1) 222 | (6908, 36, 15, 2, 1180, 1160, 1) 223 | (6909, 36, 12, 1, 223, 1107, 1) 224 | (6939, 36, 8, 4, 1927, 107, 1) 225 | (6947, 36, 8, 2, 1984, 156, 1) 226 | (6970, 36, 15, 1, 1779, 174, 1) 227 | (6997, 20, 10, 3, 1378, 479, 1) -------------------------------------------------------------------------------- /CodeCraft-2019/src/CodeCraft-2019.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | from collections import defaultdict as InitialDict 3 | import logging 4 | import sys 5 | from heapq import * 6 | 7 | numOfCar = 1 #每个路口每次需要计算路径的车辆数 8 | NUMMAX = 2 #每组非优先级车需要延迟的时间单位,以优先级车出发的最大时间为一个单位 9 | 10 | ratio = 0.3 11 | 12 | logging.basicConfig(level=logging.DEBUG, 13 | filename='../logs/CodeCraft-2019.log', 14 | format='[%(asctime)s] %(levelname)s [%(funcName)s: %(filename)s, %(lineno)d] %(message)s', 15 | datefmt='%Y-%m-%d %H:%M:%S', 16 | filemode='a') 17 | 18 | 19 | def readRoad(road_path): 20 | maxRoadLength = 0 21 | maxRoadSpeed = 0 22 | maxRoadLines = 0 23 | numOfAllLines = 0 24 | modifyFlag = 0 25 | 26 | timePlus = 50 27 | lengthCoff = 3 28 | speedCoff = 1.5 29 | linesCoff = 0.55 30 | modifyCoff = 1.0 31 | 32 | roadInfoListAll = [] 33 | StartTimeList = [] 34 | StartTimeListPriority = [] 35 | roadIndexRoadDict = {} 36 | with open(road_path, 'r') as roadTxt: 37 | roadInfoList = roadTxt.readlines() 38 | 39 | roadInfoListSize = len(roadInfoList) 40 | for i in range(1, roadInfoListSize): 41 | roadInfoList[i] = roadInfoList[i].rstrip('\n') 42 | if roadInfoList[i] == "": 43 | continue 44 | else: 45 | skiproadInfo = roadInfoList[i].strip('(').rstrip(')').split(',') 46 | dictRoadTmp1 = {'id': int(skiproadInfo[0]), 'length': int(skiproadInfo[1]), 47 | 'maxSpeed': int(skiproadInfo[2]), 48 | 'lines': int(skiproadInfo[3]), 'begin': int(skiproadInfo[4]), 'end': int(skiproadInfo[5]), 49 | 'twoWay': int(skiproadInfo[6]), 'numOfUse': 0} 50 | numOfAllLines += dictRoadTmp1['lines'] 51 | roadInfoListAll.append(dictRoadTmp1) 52 | roadIndexRoadDict[int(skiproadInfo[0])] = dictRoadTmp1 53 | 54 | # 找到最长的路,便于归一化 55 | if maxRoadLength < dictRoadTmp1['length']: 56 | maxRoadLength = dictRoadTmp1['length'] 57 | 58 | if maxRoadSpeed < dictRoadTmp1['maxSpeed']: 59 | maxRoadSpeed = dictRoadTmp1['maxSpeed'] 60 | 61 | if maxRoadLines < dictRoadTmp1['lines']: 62 | maxRoadLines = dictRoadTmp1['lines'] 63 | 64 | if dictRoadTmp1['id'] == 5000 and modifyFlag == 0: 65 | 66 | timePlus = 50 67 | lengthCoff = 3 68 | speedCoff = 1.5 69 | linesCoff = 0.55 70 | modifyCoff = 1.0 71 | 72 | # 第一张地图非优先级超参数 73 | mapOneFirstOrder = 1200 74 | mapOneSecondOrder = 1200 75 | mapOneThirdOrder = 750 76 | mapOneForthOrder = 750 77 | 78 | # 第一张地图优先级超参数 79 | mapOneFirstOrderPriority = 0 80 | mapOneSecondOrderPriority = 0 81 | mapOneThirdOrderPriority = 20 82 | mapOneForthOrderPriority = 20 83 | 84 | 85 | StartTimeList = [mapOneFirstOrder, mapOneSecondOrder, 86 | mapOneThirdOrder, mapOneForthOrder] 87 | 88 | StartTimeListPriority = [mapOneFirstOrderPriority, mapOneSecondOrderPriority, 89 | mapOneThirdOrderPriority, mapOneForthOrderPriority] 90 | 91 | modifyFlag = 1 92 | 93 | #第二张图 94 | if dictRoadTmp1['id'] == 5007 and modifyFlag == 0: 95 | timePlus = 50 96 | lengthCoff = 3 97 | speedCoff = 1.5 98 | linesCoff = 0.55 99 | modifyCoff = 1.0 100 | 101 | #第二张地图非优先级超参数 102 | mapTwoFirstOrder = 700 103 | mapTwoSecondOrder = 700 104 | mapTwoThirdOrder = 1050 105 | mapTwoForthOrder = 1050 106 | 107 | # 第二张地图优先级超参数 108 | mapTwoFirstOrderPriority = 0 109 | mapTwoSecondOrderPriority = 0 110 | mapTwoThirdOrderPriority = 20 111 | mapTwoForthOrderPriority = 20 112 | 113 | 114 | StartTimeList = [mapTwoFirstOrder, mapTwoSecondOrder, 115 | mapTwoThirdOrder, mapTwoForthOrder] 116 | 117 | StartTimeListPriority = [mapTwoFirstOrderPriority, mapTwoSecondOrderPriority, 118 | mapTwoThirdOrderPriority, mapTwoForthOrderPriority] 119 | 120 | modifyFlag = 1 121 | 122 | if 1 == dictRoadTmp1['twoWay']: 123 | dictRoadTmp2 = {'id': int(skiproadInfo[0]), 'length': int(skiproadInfo[1]), 124 | 'maxSpeed': int(skiproadInfo[2]), 125 | 'lines': int(skiproadInfo[3]), 'begin': int(skiproadInfo[5]), 126 | 'end': int(skiproadInfo[4]), 'twoWay': int(skiproadInfo[6]), 'numOfUse': 0} 127 | numOfAllLines += dictRoadTmp2['lines'] 128 | roadInfoListAll.append(dictRoadTmp2) 129 | roadIndexRoadDict[int(skiproadInfo[0])] = dictRoadTmp2 130 | return roadInfoListAll, roadIndexRoadDict, maxRoadLength, maxRoadSpeed, maxRoadLines, \ 131 | numOfAllLines, StartTimeList, StartTimeListPriority, timePlus, lengthCoff, speedCoff, linesCoff, modifyCoff 132 | 133 | 134 | #利用邻接矩阵创建图 135 | INFDEFAULT = 100000 136 | def creatInitialGraphAndCrossToRoad(numOfCrossInfoDict, roadInfoListAll, crossIndexNumDict): 137 | crossToRoad = [] 138 | graphWeight = [] 139 | Graph = [] 140 | 141 | crossToRoad = [[-1 for i in range(numOfCrossInfoDict + 1)] for j in range(numOfCrossInfoDict + 1)] 142 | for i in range(0,numOfCrossInfoDict + 1): 143 | for j in range(0, numOfCrossInfoDict + 1): 144 | crossToRoad[i][j] = 0 145 | 146 | graphWeight = [[-1 for i in range(numOfCrossInfoDict + 1)] for j in range(numOfCrossInfoDict + 1)] 147 | for i in range(0,numOfCrossInfoDict + 1): 148 | for j in range(0, numOfCrossInfoDict + 1): 149 | if i != j: 150 | graphWeight[i][j] = INFDEFAULT 151 | else: 152 | graphWeight[i][j] = 0 153 | 154 | # 对邻接矩阵和权重矩阵赋值 155 | roadInfoListAllSize = len(roadInfoListAll) 156 | for m in range(0, roadInfoListAllSize): 157 | indexNumx = crossIndexNumDict[roadInfoListAll[m]['begin']] 158 | indexNumy = crossIndexNumDict[roadInfoListAll[m]['end']] 159 | 160 | crossToRoad[indexNumx][indexNumy] = roadInfoListAll[m]['id'] 161 | graphWeight[indexNumx][indexNumy] = roadInfoListAll[m]['length'] 162 | 163 | # 创建图 164 | graphWeightRowSize = len(graphWeight) 165 | graphWeightColSize = len(graphWeight[0]) 166 | for m in range(0, graphWeightRowSize): 167 | for n in range(0, graphWeightColSize): 168 | if m != n and graphWeight[m][n] != INFDEFAULT: 169 | weightMN = graphWeight[m][n] 170 | Graph.append((m, n, weightMN)) 171 | return Graph, crossToRoad 172 | 173 | 174 | def changeWeight(numOfCrossInfoDict, roadInfoListAll, roadIndexRoadDict, maxLength, maxSpeed, maxLines, crossIndexNumDict, A, 175 | lengthCoff, speedCoff, linesCoff, modifyCoff): 176 | graphWeight = [] 177 | Graph = [] 178 | 179 | graphWeight = [[-1 for i in range(numOfCrossInfoDict + 1)] for j in range(numOfCrossInfoDict + 1)] 180 | for i in range(0,numOfCrossInfoDict + 1): 181 | for j in range(0, numOfCrossInfoDict + 1): 182 | if i != j: 183 | graphWeight[i][j] = INFDEFAULT 184 | else: 185 | graphWeight[i][j] = 0 186 | 187 | # 对邻接矩阵和权重矩阵赋值 188 | roadInfoListAllSize = len(roadInfoListAll) 189 | for m in range(0, roadInfoListAllSize): 190 | #print(roadInfoListAll[m]['id']) 191 | twoWayCoff = 1 192 | if roadInfoListAll[m]['twoWay'] == 0: 193 | twoWayCoff = 3 194 | 195 | B = 1.0 * roadIndexRoadDict[roadInfoListAll[m]['id']]['numOfUse'] / roadInfoListAll[m]['lines'] 196 | lengthVar = 1.0 * roadInfoListAll[m]['length'] / maxLength 197 | speedVar = 1.0 * maxSpeed / roadInfoListAll[m]['maxSpeed'] 198 | linesVar = 1.0 * maxLines / roadInfoListAll[m]['lines'] 199 | GoldWeight = twoWayCoff * (lengthCoff * lengthVar+ speedCoff * speedVar + modifyCoff * (B / A) + linesCoff * linesVar) 200 | 201 | indexNumx = crossIndexNumDict[roadInfoListAll[m]['begin']] 202 | indexNumy = crossIndexNumDict[roadInfoListAll[m]['end']] 203 | 204 | graphWeight[indexNumx][indexNumy] = GoldWeight 205 | 206 | # 创建图 207 | graphWeightRowSize = len(graphWeight) 208 | graphWeightColSize = len(graphWeight[0]) 209 | for m in range(0, graphWeightRowSize): 210 | for n in range(0, graphWeightColSize): 211 | if m != n and graphWeight[m][n] != INFDEFAULT: 212 | weightMN = graphWeight[m][n] 213 | Graph.append((m, n, weightMN)) 214 | return Graph 215 | 216 | 217 | #根据路口找路 218 | def crossIndexRoad(crossToRoad, crossList): 219 | roadList = [] 220 | rangeSize = len(crossList) - 1 221 | for i in range(0, rangeSize): 222 | cross1 = crossList[i] 223 | cross2 = crossList[i + 1] 224 | roadList.append(crossToRoad[cross1][cross2]) 225 | return roadList 226 | 227 | 228 | def calculateLengthAndPath(Graph, graphTmp, vBegin, vEnd, direction): 229 | beginID = vBegin 230 | endID = vEnd 231 | priorQueue, exitPath = [(0, beginID, ())], set() 232 | 233 | while priorQueue: 234 | (sumWeight, left, path) = heappop(priorQueue) 235 | 236 | if left not in exitPath: 237 | exitPath.add(left) 238 | path = (left, path) 239 | if left == endID: 240 | return sumWeight, path 241 | 242 | if direction == 0: 243 | for curWeight, right in graphTmp.get(left, ()): 244 | if right not in exitPath: 245 | heappush(priorQueue, (sumWeight + curWeight, right, path)) 246 | elif direction == 1: 247 | for curWeight, right in graphTmp.get(left, ()): 248 | if right < left: 249 | continue 250 | if right not in exitPath: 251 | heappush(priorQueue, (sumWeight + curWeight, right, path)) 252 | elif direction == 2: 253 | for curWeight, right in graphTmp.get(left, ()): 254 | if right > left: 255 | continue 256 | if right not in exitPath: 257 | heappush(priorQueue, (sumWeight + curWeight, right, path)) 258 | elif direction == 3: 259 | for curWeight, right in graphTmp.get(left, ()): 260 | if (right - left != 1) and (right - left != (-1 * 10)): 261 | continue 262 | if right not in exitPath: 263 | heappush(priorQueue, (sumWeight + curWeight, right, path)) 264 | elif direction == 4: 265 | for curWeight, right in graphTmp.get(left, ()): 266 | if (right - left != -1) and (right - left != 10): 267 | continue 268 | if right not in exitPath: 269 | heappush(priorQueue, (sumWeight + curWeight, right, path)) 270 | return INFDEFAULT, [] 271 | 272 | 273 | def dijkstraCarPath(Graph, vBegin, vEnd, direction): 274 | GraphTmp = Graph 275 | beginID = vBegin 276 | endID = vEnd 277 | directionFlag = direction 278 | 279 | graphBinary = InitialDict(list) 280 | 281 | for left, right, curWeight in Graph: 282 | graphBinary[left].append((curWeight, right)) 283 | 284 | calLength, drivePathQueue = calculateLengthAndPath(GraphTmp, graphBinary, beginID, endID, directionFlag) 285 | 286 | pathLength = -1 287 | drivePath = [] 288 | drivePathQueueSize = len(drivePathQueue) 289 | if drivePathQueueSize > 0: 290 | pathLength = calLength 291 | left = drivePathQueue[0] 292 | drivePath.append(left) 293 | right = drivePathQueue[1] 294 | 295 | rightSize = len(right) 296 | while rightSize > 0: 297 | left = right[0] 298 | drivePath.append(left) 299 | right = right[1] 300 | rightSize = len(right) 301 | drivePath.reverse() 302 | 303 | return pathLength, drivePath 304 | 305 | 306 | #CROSSDICT字典,key为crossid,value为道路列表 307 | def readCrossFirst(cross_path): 308 | crossIDList = [] 309 | crossInfoDictFirst = {} 310 | isVisit = {} 311 | with open(cross_path, 'r') as crossTxt: 312 | crossInfoList = crossTxt.readlines() 313 | crossInfoListSize = len(crossInfoList) 314 | for i in range(1, crossInfoListSize): 315 | crossInfoList[i] = crossInfoList[i].rstrip('\n') 316 | if crossInfoList[i] == "": 317 | continue 318 | else: 319 | skipcrossInfo = crossInfoList[i].strip('(').rstrip(')').split(',') 320 | id = skipcrossInfo[0] 321 | right = skipcrossInfo[1] 322 | down = skipcrossInfo[2] 323 | left = skipcrossInfo[3] 324 | up = skipcrossInfo[4] 325 | crossIDList.append(int(id)) 326 | isVisit[int(id)] = False 327 | crossInfoDictFirst[int(id)] = [int(right), int(down), int(left), int(up)] 328 | 329 | return crossIDList, isVisit, crossInfoDictFirst 330 | 331 | 332 | def customDirection(crossId, isVisit, crossInfoDictFirst, roadInfoListAll, direction=None, preCrossId=None): 333 | if isVisit[crossId]: 334 | return 335 | isVisit[crossId] = True 336 | if preCrossId is not None: 337 | for i in range(4): 338 | roadId = crossInfoDictFirst[crossId][i] 339 | if roadId != -1: 340 | roadInfoListAllSize = len(roadInfoListAll) 341 | for m in range(roadInfoListAllSize): 342 | if roadId == roadInfoListAll[m]['id']: 343 | preCrossID = roadInfoListAll[m]['begin'] if roadInfoListAll[m]['begin'] != crossId else \ 344 | roadInfoListAll[m]['end'] 345 | if preCrossID == preCrossId: 346 | shift = i - (direction + 2) % 4 347 | crossInfoDictFirst[crossId] = [crossInfoDictFirst[crossId][shift%4], 348 | crossInfoDictFirst[crossId][(1+shift)%4], 349 | crossInfoDictFirst[crossId][(2+shift)%4], 350 | crossInfoDictFirst[crossId][(3+shift)%4]] 351 | break 352 | for i in range(4): 353 | roadId = crossInfoDictFirst[crossId][i] 354 | if roadId != -1: 355 | roadInfoListAllSize = len(roadInfoListAll) 356 | for m in range(roadInfoListAllSize): 357 | if roadId == roadInfoListAll[m]['id']: 358 | nextCrossId = roadInfoListAll[m]['begin'] if roadInfoListAll[m]['begin'] != crossId else \ 359 | roadInfoListAll[m]['end'] 360 | customDirection(nextCrossId, isVisit, crossInfoDictFirst, roadInfoListAll, i, crossId) 361 | 362 | 363 | def readCrossSecond(crossIDList, crossInfoDictFirst, isVisit, roadInfoListAll): 364 | customDirection(crossIDList[0], isVisit, crossInfoDictFirst, roadInfoListAll) 365 | crossInfoDict = {} 366 | crossIndexNumDict = {} 367 | numCarInCurCross = {} 368 | i = 0 369 | for crossId in crossIDList: 370 | i += 1 371 | right, down, left, up = crossInfoDictFirst[crossId] 372 | dictTmp = {'id': i, 'roadIDRight': int(right), 373 | 'roadIDDown': int(down), 374 | 'roadIDLeft': int(left), 'roadIDUp': int(up)} 375 | crossIndexNumDict[crossId] = i 376 | crossInfoDict[dictTmp['id']] = dictTmp 377 | numCarInCurCross[crossId] = 0 378 | return crossInfoDict, numCarInCurCross, crossIndexNumDict 379 | 380 | 381 | #读路口信息,建立索引信息 382 | def readCross(cross_path): 383 | # 读取cross文件 384 | crossIndexNumDict = {} 385 | crossInfoDict = {} 386 | numCarInCurCross = {} 387 | with open(cross_path, 'r') as crossTxt: 388 | crossInfoList = crossTxt.readlines() 389 | crossInfoListSize = len(crossInfoList) 390 | for i in range(1, crossInfoListSize): 391 | crossInfoList[i] = crossInfoList[i].rstrip('\n') 392 | if crossInfoList[i] == "": 393 | continue 394 | else: 395 | skipcrossInfo = crossInfoList[i].strip('(').rstrip(')').split(',') 396 | dictTmp = {'id': i, 'roadIDRight': int(skipcrossInfo[1]), 397 | 'roadIDDown': int(skipcrossInfo[2]), 398 | 'roadIDLeft': int(skipcrossInfo[3]), 'roadIDUp': int(skipcrossInfo[4])} 399 | #两张地图路口一样,路口编号按行顺序给出且地图完整为矩形,但与序号一致或不一致 400 | crossIndexNumDict[int(skipcrossInfo[0])] = i 401 | 402 | crossInfoDict[dictTmp['id']] = dictTmp 403 | numCarInCurCross[int(skipcrossInfo[0])] = 0 404 | return crossInfoDict, numCarInCurCross, crossIndexNumDict 405 | 406 | 407 | #读车辆信息,车辆字典里加组别,dijkstra计算总棋盘距离,然后分组 408 | def readCar(car_path, crossIndexNumDict, numCarInCurCross, Graph, crossInfoDict, crossToRoad): 409 | carInfoDict = {} 410 | persetCarInfoDict = {} 411 | crossIndexCar = InitialDict(list) 412 | numOfAllCarChessBoardPath = 0 413 | maxNumOfCarInCross = 0 414 | priorityCarOfPresetInfoDict = {} 415 | oridinaryCarOfPresetInfoDict = {} 416 | numCarOfPreset = 0 417 | 418 | with open(car_path, 'r') as carTxt: 419 | carInfoList = carTxt.readlines() 420 | 421 | carInfoListSize = len(carInfoList) 422 | for i in range(1, carInfoListSize): 423 | carInfoList[i] = carInfoList[i].rstrip('\n') 424 | if carInfoList[i] == "": 425 | continue 426 | else: 427 | skipcarInfo = carInfoList[i].strip('(').rstrip(')').split(',') 428 | #考虑预设车辆 429 | if int(skipcarInfo[6]) == 1: 430 | dictTmp = {'id': int(skipcarInfo[0]), 'begin': int(skipcarInfo[1]), 'end': int(skipcarInfo[2]), 431 | 'maxSpeed': int(skipcarInfo[3]), 'planTime': int(skipcarInfo[4]), 'group': 0, 432 | 'priority': int(skipcarInfo[5]), 'preset': int(skipcarInfo[6])} 433 | if int(skipcarInfo[5]) == 1: 434 | priorityCarOfPresetInfoDict[int(skipcarInfo[0])] = dictTmp 435 | else: 436 | oridinaryCarOfPresetInfoDict[int(skipcarInfo[0])] = dictTmp 437 | persetCarInfoDict[int(skipcarInfo[0])] = dictTmp 438 | continue 439 | dictTmp = {'id': int(skipcarInfo[0]), 'begin': int(skipcarInfo[1]), 'end': int(skipcarInfo[2]), 440 | 'maxSpeed': int(skipcarInfo[3]), 'planTime': int(skipcarInfo[4]), 'group': 0, 441 | 'priority': int(skipcarInfo[5]), 'preset': int(skipcarInfo[6])} 442 | 443 | #这里是否需要考虑预设车辆??? 444 | #不需要转换为序号,直接路口编号即可 445 | numCarInCurCross[dictTmp['begin']] += 1 446 | 447 | beginID = crossIndexNumDict[dictTmp['begin']] 448 | endID = crossIndexNumDict[dictTmp['end']] 449 | 450 | #普通dijktra求出最短路径 451 | #roadTmpList是cross,roadPath是路 452 | roadTmpList = dijkstraCarPath(Graph, beginID, endID, 0) 453 | roadPath = crossIndexRoad(crossToRoad, roadTmpList[1]) 454 | roadPathSize = len(roadPath) 455 | numRight = 0 456 | numDown = 0 457 | numLeft = 0 458 | numUp = 0 459 | for j in range(0, roadPathSize): 460 | roadID = roadPath[j] 461 | crossID = roadTmpList[1][j] 462 | if roadID == crossInfoDict[crossID]['roadIDRight']: 463 | numRight += 1 464 | elif roadID == crossInfoDict[crossID]['roadIDDown']: 465 | numDown += 1 466 | elif roadID == crossInfoDict[crossID]['roadIDLeft']: 467 | numLeft += 1 468 | elif roadID == crossInfoDict[crossID]['roadIDUp']: 469 | numUp += 1 470 | if numRight > numLeft: 471 | if numUp > numDown: 472 | dictTmp['group'] = 3 473 | if numUp == numDown: 474 | dictTmp['group'] = 1 475 | if numUp < numDown: 476 | dictTmp['group'] = 1 477 | elif numRight < numLeft: 478 | if numUp > numDown: 479 | dictTmp['group'] = 2 480 | if numUp == numDown: 481 | dictTmp['group'] = 2 482 | if numUp < numDown: 483 | dictTmp['group'] = 4 484 | else: 485 | if numUp > numDown: 486 | dictTmp['group'] = 3 487 | if numUp == numDown: 488 | dictTmp['group'] = 1 489 | if numUp < numDown: 490 | dictTmp['group'] = 4 491 | 492 | #棋盘距离,roadPath的size 493 | numOfAllCarChessBoardPath += len(roadPath) 494 | 495 | carInfoDict[int(skipcarInfo[0])] = dictTmp 496 | crossIndexCar[beginID].append(dictTmp['id']) 497 | tmpDict = sorted(numCarInCurCross.items(),key=lambda x:x[1],reverse=True) 498 | maxNumOfCarInCross = tmpDict[0][1] 499 | return carInfoDict, numOfAllCarChessBoardPath, crossIndexCar, maxNumOfCarInCross, persetCarInfoDict, priorityCarOfPresetInfoDict, oridinaryCarOfPresetInfoDict 500 | 501 | 502 | #处理预设车辆信息,将路径存入各自的字典 503 | #包括车辆ID和预设路径,将预设车辆中的优先级车辆和非优先级车辆分开,并按照路径的长度从大到小排序 504 | def readPreset(preset_answer_path, persetCarInfoDict): 505 | presetPathDict = {} 506 | priorityCarPathOfPresetDictTmp = {} 507 | ordinaryCarPathOfPresetDictTmp = {} 508 | priorityCarOfPresetID = [] 509 | ordinaryCarOfPresetID = [] 510 | with open(preset_answer_path, 'r') as presetCarTxt: 511 | presetCarInfoList = presetCarTxt.readlines() 512 | 513 | presetCarInfoListSize = len(presetCarInfoList) 514 | for i in range(1, presetCarInfoListSize): 515 | presetCarInfoList[i] = presetCarInfoList[i].rstrip('\n') 516 | if presetCarInfoList[i] == "": 517 | continue 518 | else: 519 | skippersetCarInfo = presetCarInfoList[i].strip('(').rstrip(')').split(',') 520 | skippersetCarInfoSize = len(skippersetCarInfo) 521 | presetCarRoadPath = [] 522 | for i in range(2, skippersetCarInfoSize): 523 | presetCarRoadPath.append(int(skippersetCarInfo[i])) 524 | dictTmp = {"pathSize": len(presetCarRoadPath), "path": presetCarRoadPath, "startTime": int(skippersetCarInfo[1])} 525 | if persetCarInfoDict[int(skippersetCarInfo[0])]['priority'] == 1: 526 | priorityCarPathOfPresetDictTmp[int(skippersetCarInfo[0])] = dictTmp 527 | else: 528 | ordinaryCarPathOfPresetDictTmp[int(skippersetCarInfo[0])] = dictTmp 529 | presetPathDict[int(skippersetCarInfo[0])] = dictTmp 530 | # print(int(skippersetCarInfo[0])," : ", presetCarRoadPath ) 531 | 532 | priorityCarPathOfPresetDict = sorted(priorityCarPathOfPresetDictTmp.items(),key=lambda x:x[1]['pathSize'], 533 | reverse=True) 534 | ordinaryCarPathOfPresetDict = sorted(ordinaryCarPathOfPresetDictTmp.items(), key=lambda x: x[1]['pathSize'], 535 | reverse=True) 536 | 537 | #将按照路径长短排序后的车辆ID分别存入优先车队和普通车队 538 | for i in range(0, len(priorityCarPathOfPresetDict)): 539 | priorityCarOfPresetID.append(priorityCarPathOfPresetDict[i][0]) 540 | for i in range(0, len(ordinaryCarPathOfPresetDict)): 541 | ordinaryCarOfPresetID.append(ordinaryCarPathOfPresetDict[i][0]) 542 | 543 | return presetPathDict, priorityCarOfPresetID, ordinaryCarOfPresetID 544 | 545 | #从预设车辆中选择30%的车辆自己规划路线,三个思路 546 | #(1)选择优先级高的车辆, 547 | #(2)选择出发时间靠后的车辆, 548 | #(3)选择路线长的车辆 549 | def selectCar(presetPathDict, persetCarInfoDict, priorityCarOfPresetID, ordinaryCarOfPresetID, carInfoDict, 550 | numOfAllCarChessBoardPath, crossIndexCar, crossIndexNumDict, numCarInCurCross, Graph, crossInfoDict, 551 | crossToRoad, maxNumOfCarInCross): 552 | print(numOfAllCarChessBoardPath, " ", maxNumOfCarInCross) 553 | selectCarID = [] 554 | priorityCarOfPresetIDUpdate = [] 555 | ordinaryCarOfPresetIDUpdate = [] 556 | numOfSelectcar = int(len(persetCarInfoDict) * ratio) 557 | #若选择的车辆数目小于预设车辆中的优先级车来嗯 558 | if len(priorityCarOfPresetID) >= numOfSelectcar: 559 | priorityCarOfPresetIDUpdate = priorityCarOfPresetID[:] 560 | for i in range(0, numOfSelectcar): 561 | selectCarID.append(priorityCarOfPresetID[i]) 562 | priorityCarOfPresetIDUpdate.remove(priorityCarOfPresetID[i]) #这里删除元素对不对?? 563 | 564 | elif len(priorityCarOfPresetID) < numOfSelectcar: 565 | selectCarID = priorityCarOfPresetID[:] 566 | ordinaryCarOfPresetIDUpdate = ordinaryCarOfPresetID[:] 567 | numOfReserveSelectCar = numOfSelectcar - len(priorityCarOfPresetID) 568 | for i in range(0, numOfReserveSelectCar): 569 | selectCarID.append(ordinaryCarOfPresetID[i]) 570 | ordinaryCarOfPresetIDUpdate.remove(ordinaryCarOfPresetID[i]) 571 | 572 | print(len(selectCarID), " ", len(persetCarInfoDict) * ratio) 573 | 574 | #选择完车辆后,将选择出来的车辆更新进普通车队,更新预设车队 575 | for i in range(0, len(selectCarID)): 576 | del presetPathDict[selectCarID[i]] 577 | 578 | dictTmp = persetCarInfoDict[selectCarID[i]] 579 | numCarInCurCross[dictTmp['begin']] += 1 580 | 581 | beginID = crossIndexNumDict[dictTmp['begin']] 582 | endID = crossIndexNumDict[dictTmp['end']] 583 | 584 | # 普通dijktra求出最短路径 585 | # roadTmpList是cross,roadPath是路 586 | roadTmpList = dijkstraCarPath(Graph, beginID, endID, 0) 587 | roadPath = crossIndexRoad(crossToRoad, roadTmpList[1]) 588 | roadPathSize = len(roadPath) 589 | numRight = 0 590 | numDown = 0 591 | numLeft = 0 592 | numUp = 0 593 | for j in range(0, roadPathSize): 594 | roadID = roadPath[j] 595 | crossID = roadTmpList[1][j] 596 | if roadID == crossInfoDict[crossID]['roadIDRight']: 597 | numRight += 1 598 | elif roadID == crossInfoDict[crossID]['roadIDDown']: 599 | numDown += 1 600 | elif roadID == crossInfoDict[crossID]['roadIDLeft']: 601 | numLeft += 1 602 | elif roadID == crossInfoDict[crossID]['roadIDUp']: 603 | numUp += 1 604 | if numRight > numLeft: 605 | if numUp > numDown: 606 | dictTmp['group'] = 3 607 | if numUp == numDown: 608 | dictTmp['group'] = 1 609 | if numUp < numDown: 610 | dictTmp['group'] = 1 611 | elif numRight < numLeft: 612 | if numUp > numDown: 613 | dictTmp['group'] = 2 614 | if numUp == numDown: 615 | dictTmp['group'] = 2 616 | if numUp < numDown: 617 | dictTmp['group'] = 4 618 | else: 619 | if numUp > numDown: 620 | dictTmp['group'] = 3 621 | if numUp == numDown: 622 | dictTmp['group'] = 1 623 | if numUp < numDown: 624 | dictTmp['group'] = 4 625 | 626 | # 棋盘距离,roadPath的size 627 | numOfAllCarChessBoardPath += len(roadPath) 628 | 629 | crossIndexCar[beginID].append(dictTmp['id']) 630 | carInfoDict[selectCarID[i]] = persetCarInfoDict[selectCarID[i]] 631 | tmpDict = sorted(numCarInCurCross.items(), key=lambda x: x[1], reverse=True) 632 | maxNumOfCarInCross = tmpDict[0][1] 633 | return numOfAllCarChessBoardPath, maxNumOfCarInCross 634 | 635 | 636 | #更新每条预设路的使用次数 637 | def presetChangeNumuse(presetPathDict, roadIndexRoadDict): 638 | presetPathDictKeys = presetPathDict.keys() 639 | sortPresetPathDict = sorted(presetPathDictKeys) 640 | 641 | for mKeys in sortPresetPathDict: 642 | mValues = presetPathDict[mKeys]['path'] 643 | # print(mValues) 644 | for k in mValues: 645 | # print(roadIndexRoadDict[k]['numOfUse']) 646 | roadIndexRoadDict[k]['numOfUse'] = roadIndexRoadDict[k]['numOfUse'] + 1 647 | 648 | 649 | def writeAnswer(answer_path, answerDict): 650 | with open(answer_path, 'w') as answerTxt: 651 | title = '#(carId,StartTime,RoadId...)' + '\n' 652 | answerTxt.write(title) 653 | answerKeys = answerDict.keys() 654 | #顺序输出 655 | sortAnswer = sorted(answerKeys) 656 | 657 | sortAnswerSize = len(sortAnswer) 658 | for m in range(0, sortAnswerSize): 659 | text = sortAnswer[m] 660 | writeTxt = '' 661 | answerDictTextSize = len(answerDict[text]) 662 | for n in range(0, answerDictTextSize): 663 | specificText = answerDict[text][n] 664 | if 0 == n: 665 | writeTxt += '(' + str(specificText) 666 | else: 667 | writeTxt += ', ' + str(specificText) 668 | 669 | writeTxt += ')' + '\n' 670 | answerTxt.write(writeTxt) 671 | 672 | answerTxt.close() 673 | 674 | 675 | def DynamicDrivePath(numOfCrossInfoDict, roadInfoListAll, maxRoadLength, maxRoadSpeed, 676 | maxRoadLines, crossIndexNumDict, A, carInfoDict, maxNumOfCarInCross, numOfCar, 677 | crossIndexCar, crossToRoad, roadIndexRoadDict, lengthCoff, speedCoff, linesCoff, modifyCoff): 678 | # 初始化最终出发时间 679 | allCarPath = [] 680 | for i in range(0, 4): 681 | allCarPath.append(InitialDict(list)) 682 | 683 | # 循环更新路径的次数 684 | for i in range(0, maxNumOfCarInCross // numOfCar): 685 | 686 | Graph = changeWeight(numOfCrossInfoDict, roadInfoListAll, roadIndexRoadDict, maxRoadLength, maxRoadSpeed, 687 | maxRoadLines, crossIndexNumDict, A, lengthCoff, speedCoff, linesCoff, modifyCoff) 688 | # 循环路口 689 | for cross in crossIndexCar.keys(): 690 | for j in range(numOfCar): 691 | if j < len(crossIndexCar[cross]): 692 | #beginID = crossIndexNumDict[cross] 693 | beginID = cross 694 | endID = crossIndexNumDict[carInfoDict[crossIndexCar[cross][j]]['end']] 695 | ID = carInfoDict[crossIndexCar[cross][j]]['id'] 696 | planTime = carInfoDict[crossIndexCar[cross][j]]['planTime'] 697 | maxspeed = carInfoDict[crossIndexCar[cross][j]]['maxSpeed'] 698 | group = carInfoDict[crossIndexCar[cross][j]]['group'] 699 | priority = carInfoDict[crossIndexCar[cross][j]]['priority'] 700 | crossIndexCar[cross].pop(j) 701 | 702 | roadTmpList = dijkstraCarPath(Graph, beginID, endID, 0) 703 | 704 | roadPath = crossIndexRoad(crossToRoad, roadTmpList[1]) 705 | for k in roadPath: 706 | roadIndexRoadDict[k]['numOfUse'] = roadIndexRoadDict[k]['numOfUse'] + 1 707 | dictTmp = {'id': ID, 'start': planTime, 'drivePath': roadPath, 'priority': priority} 708 | allCarPath[group - 1][maxspeed].append(dictTmp) 709 | 710 | return allCarPath 711 | 712 | 713 | # 速度降序排列,改变出发时间 714 | def changeTimePlus(allCarPath, StartTimeList, StartTimeListPriority, timePlus): 715 | answerDict = InitialDict(list) 716 | allCarPathSize = len(allCarPath) 717 | #修改每组车辆的时间 718 | for m in range(0, allCarPathSize): 719 | if len(allCarPath[m]) != 0: 720 | # speedList = {v1:{}, v2:{}...} 721 | # 升序排列,再反转 722 | allCarPathMKeys = allCarPath[m].keys() 723 | speedList = sorted(allCarPathMKeys) 724 | speedList.reverse() 725 | speedListSize = len(speedList) 726 | for num in range(0, speedListSize): 727 | textPathDict = speedList[num] 728 | extraTime = num * timePlus 729 | allCarPathtextPathDictSize = len(allCarPath[m][textPathDict]) 730 | for text in range(0, allCarPathtextPathDictSize): 731 | ID = allCarPath[m][textPathDict][text]['id'] 732 | whichCarID = allCarPath[m][textPathDict][text]['id'] 733 | priority = allCarPath[m][textPathDict][text]['priority'] 734 | 735 | #优先级高的车辆自己分组发车,与非优先级的车分开 736 | if priority == 1: 737 | startTime = allCarPath[m][textPathDict][text]['start'] + extraTime + StartTimeListPriority[m] 738 | else: 739 | startTime = allCarPath[m][textPathDict][text]['start'] + extraTime + StartTimeList[m] 740 | 741 | answerDict[whichCarID].append(ID) 742 | answerDict[whichCarID].append(startTime) 743 | 744 | drivePathSize = len(allCarPath[m][textPathDict][text]['drivePath']) 745 | for path in range(0, drivePathSize): 746 | whichRoad = allCarPath[m][textPathDict][text]['drivePath'][path] 747 | answerDict[whichCarID].append(whichRoad) 748 | return answerDict 749 | 750 | 751 | # #将优先级车辆分组发车(或者一起发车),非优先级车辆分组发车(或一起发车) 752 | # def 753 | 754 | def main(): 755 | if len(sys.argv) != 6: 756 | logging.info('please input args: car_path, road_path, cross_path, answerPath') 757 | exit(1) 758 | 759 | car_path = sys.argv[1] 760 | road_path = sys.argv[2] 761 | cross_path = sys.argv[3] 762 | preset_answer_path = sys.argv[4] 763 | answer_path = sys.argv[5] 764 | 765 | 766 | # car_path = '/home/qgy/HW/SDKHW/SDK/2-map-training-1/car.txt' 767 | # road_path = '/home/qgy/HW/SDKHW/SDK/2-map-training-1/road.txt' 768 | # cross_path = '/home/qgy/HW/SDKHW/SDK/2-map-training-1/cross.txt' 769 | # answer_path = '/home/qgy/HW/SDKHW/SDK/2-map-training-1/answer.txt' 770 | # preset_answer_path = '/home/qgy/HW/SDKHW/SDK/2-map-training-1/presetAnswer.txt' 771 | 772 | 773 | logging.info("car_path is %s" % (car_path)) 774 | logging.info("road_path is %s" % (road_path)) 775 | logging.info("cross_path is %s" % (cross_path)) 776 | logging.info("preset_answer_path is %s" % (preset_answer_path)) 777 | logging.info("answer_path is %s" % (answer_path)) 778 | 779 | ''' 780 | 读取文件 781 | ''' 782 | 783 | # 读取road文件 784 | roadInfoListAll, roadIndexRoadDict, maxRoadLength, maxRoadSpeed, maxRoadLines, numOfAllLines, \ 785 | StartTimeList, StartTimeListPriority, timePlus, lengthCoff, speedCoff, linesCoff, \ 786 | modifyCoff = readRoad(road_path) 787 | 788 | #读取cross文件 789 | CROSSNAMESPACE, visitDone, CROSSDICT = readCrossFirst(cross_path) 790 | crossInfoDict, numCarInCurCross, crossIndexNumDict = readCrossSecond(CROSSNAMESPACE, CROSSDICT, visitDone, roadInfoListAll) 791 | 792 | 793 | # 创建有向图 794 | numOfCrossInfoDict = len(crossInfoDict) 795 | graphInitial, crossToRoad = creatInitialGraphAndCrossToRoad(numOfCrossInfoDict, roadInfoListAll, crossIndexNumDict) 796 | 797 | # 读取car文件 798 | carInfoDict, numOfAllCarChessBoardPath, crossIndexCar, maxNumOfCarInCross, persetCarInfoDict,\ 799 | priorityCarOfPresetInfoDict, oridinaryCarOfPresetInfoDict = readCar(car_path, crossIndexNumDict, numCarInCurCross, 800 | graphInitial, crossInfoDict, crossToRoad) 801 | 802 | 803 | #读取预设车辆文件 804 | presetPathDict, priorityCarOfPresetID, ordinaryCarOfPresetID = readPreset(preset_answer_path, persetCarInfoDict) 805 | 806 | numOfAllCarChessBoardPath, maxNumOfCarInCross = selectCar(presetPathDict, persetCarInfoDict, priorityCarOfPresetID, 807 | ordinaryCarOfPresetID, carInfoDict,numOfAllCarChessBoardPath, 808 | crossIndexCar, crossIndexNumDict, numCarInCurCross, 809 | graphInitial, crossInfoDict,crossToRoad, maxNumOfCarInCross) 810 | 811 | A = 1.0 * numOfAllCarChessBoardPath / numOfAllLines 812 | 813 | #更新每条路的使用次数 814 | presetChangeNumuse(presetPathDict, roadIndexRoadDict) 815 | 816 | 817 | ''' 818 | 处理规划路径,修改出发时间 819 | ''' 820 | #搜寻最短路径 821 | allCarPath = DynamicDrivePath(numOfCrossInfoDict, roadInfoListAll, maxRoadLength, maxRoadSpeed, maxRoadLines, 822 | crossIndexNumDict, A, carInfoDict, maxNumOfCarInCross, numOfCar, crossIndexCar, 823 | crossToRoad, roadIndexRoadDict, lengthCoff, speedCoff, linesCoff, modifyCoff) 824 | 825 | #修改出发时间 826 | answerDict = changeTimePlus(allCarPath,StartTimeList, StartTimeListPriority, timePlus) 827 | 828 | #统计每组的车辆 829 | numOfRightDown = 0 830 | numOfLeftUp = 0 831 | numOfRightUp = 0 832 | numOfLeftDown = 0 833 | for kv in carInfoDict.items(): 834 | if kv[1]['group'] == 1: 835 | numOfRightDown += 1 836 | if kv[1]['group'] == 2: 837 | numOfLeftUp += 1 838 | if kv[1]['group'] == 3: 839 | numOfRightUp += 1 840 | if kv[1]['group'] == 4: 841 | numOfLeftDown += 1 842 | print(numOfRightDown) 843 | print(numOfLeftUp) 844 | print(numOfRightUp) 845 | print(numOfLeftDown) 846 | 847 | 848 | ''' 849 | 写入文件 850 | ''' 851 | # to write output file 852 | writeAnswer(answer_path, answerDict) 853 | 854 | 855 | if __name__ == "__main__": 856 | main() -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2019华为软件精英挑战赛 2 | =============== 3 | 初赛通过规划车辆路径和出发时间,使得系统调度时间最短,复赛在初赛的基础上添加优先车辆和预置车辆,我们通过自定义路权函数,伪动态更新路权和发车策略来分图调整参数,达到最优时间。 4 | 5 | 初赛思路 6 | ------------ 7 | * 发车策略 8 | * 道路顺序调整 9 | ```C++ 10 | 1. 取cross文件中第一个路口为标准,通过DFS将文件中其他道路的顺序调整为和第一个路口一致 11 | ``` 12 | 13 | * 车辆分组 14 | ```C++ 15 | 1. 道路顺序调整后,人为规定cross文件中每条路之间的关系为上、下、左、右 16 | 2. 将所有车辆按行驶路线分为四组,右下,左上,右上,左下,然后右下和左上为一组,右上和左下为一组发车 17 | 3. 通过dijkstra算法求出所有车辆的最短路径,根据每辆车走过的道路之间的关系(上下左右的数量),判断具体为哪一组 18 | 4. 调整两组车辆的发车间隔 19 | ``` 20 | 21 | * 车辆实际出发时间 22 | ```C++ 23 | 1. 将每组车辆按车辆行驶速度排序,速度大的车辆优先发车,按速度依次发车,时间间隔依次加50时间片 24 | ``` 25 | 26 | * 路权函数 27 | * 自定义路权函数 28 | ```C++ 29 | 1. 创建有向图,其中路权函数考虑了长度length、车道数lines、道路限速speed、单双向道twoWay,道路使用情况numOfUSe 30 | 2. 长度length、车道数lines、道路限速speed路权元素需要归一化,其中长度元素占比相较于其他要高 31 | 3. 测试发现,车辆死锁极易发生在单向道及其附近,其他元素相同的情况下,将单向道的权重设置比双向道高,优先走双向道 32 | 4. 当道路使用次数较多时,则默认道路阻抗较大,通过调整参数尽量少选择该道路 33 | ``` 34 | 35 | * 伪动态更新路权函数 36 | ```C++ 37 | 1. 目的:使相同起止点的车辆选择尽量选择不同的道路,另外,调整道路阻抗 38 | 2. 循环所有路口,以路口的最大发车数目为限制条件,每次路口只发一辆车,更新道路使用次数,进而更新路权函数 39 | ``` 40 | 41 | 复赛思路 42 | ------------ 43 | 复赛由于添加了预置车辆和优先车辆,并更新了评分公式,将优先车辆的调度时间单独计算。我们只改变了发车策略,优先调度预设车辆和优先车辆。另外,复赛可以重新规划不超过10%的预设车辆。 44 | 45 | * 发车策略 46 | * 车辆分组 47 | ```C++ 48 | 1. 人为规定cross文件中每条路之间的关系为上、下、左、右 49 | 2. 将非预设非优先级车辆按行驶路线分为四组,右下,左上,右上,左下,然后右下和左上为一组,右上和左下为一组发车 50 | 3. 将非预设优先级车辆同样分组 51 | 3. 通过dijkstra算法求出所有车辆的最短路径,根据每辆车走过的道路之间的关系(上下左右的数量),判断具体为哪一组 52 | 4. 调整非预设非优先级两组车辆的发车间隔,经测试,优先级可一起发车(仅对复赛、初赛数据) 53 | ``` 54 | 55 | * 车辆实际出发时间 56 | ```C++ 57 | 1. 将每组车辆按车辆行驶速度排序,速度大的车辆优先发车,按速度依次发车,时间间隔依次加50时间片 58 | 2. 先发优先级车辆,再发非预设非优先级车辆 59 | ``` 60 | * 选择策略 61 | ```C++ 62 | 1. 优先选择预设车辆中的优先级车辆 63 | 2. 若预设中优先级车辆较少,选择预设非优先车辆中预设规划路径长的车辆 64 | ``` 65 | 66 | -------------------------------------------------------------------------------- /build_and_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd CodeCraft-2019 3 | python src/CodeCraft-2019.py config/car.txt config/road.txt config/cross.txt config/presetAnswer.txt config/answer.txt -------------------------------------------------------------------------------- /logs/CodeCraft-2019.log: -------------------------------------------------------------------------------- 1 | [2018-12-17 15:47:41] INFO [main: CodeCraft-2019.py, 21] car_path is config/car.txt 2 | [2018-12-17 15:47:41] INFO [main: CodeCraft-2019.py, 22] road_path is config/road.txt 3 | [2018-12-17 15:47:41] INFO [main: CodeCraft-2019.py, 23] cross_path is config/cross.txt 4 | [2018-12-17 15:47:41] INFO [main: CodeCraft-2019.py, 24] answer_path is config/answer.txt[2019-04-12 09:39:32] INFO [main: CodeCraft-2019.py, 698] car_path is config/car.txt 5 | [2019-04-12 09:39:32] INFO [main: CodeCraft-2019.py, 699] road_path is config/road.txt 6 | [2019-04-12 09:39:32] INFO [main: CodeCraft-2019.py, 700] cross_path is config/cross.txt 7 | [2019-04-12 09:39:32] INFO [main: CodeCraft-2019.py, 701] preset_answer_path is config/presetAnswer.txt 8 | [2019-04-12 09:39:32] INFO [main: CodeCraft-2019.py, 702] answer_path is config/answer.txt 9 | [2019-04-12 09:40:28] INFO [main: CodeCraft-2019.py, 698] car_path is config/car.txt 10 | [2019-04-12 09:40:28] INFO [main: CodeCraft-2019.py, 699] road_path is config/road.txt 11 | [2019-04-12 09:40:28] INFO [main: CodeCraft-2019.py, 700] cross_path is config/cross.txt 12 | [2019-04-12 09:40:28] INFO [main: CodeCraft-2019.py, 701] preset_answer_path is config/presetAnswer.txt 13 | [2019-04-12 09:40:28] INFO [main: CodeCraft-2019.py, 702] answer_path is config/answer.txt 14 | [2019-04-16 15:39:11] INFO [main: CodeCraft-2019.py, 774] car_path is config/car.txt 15 | [2019-04-16 15:39:11] INFO [main: CodeCraft-2019.py, 775] road_path is config/road.txt 16 | [2019-04-16 15:39:11] INFO [main: CodeCraft-2019.py, 776] cross_path is config/cross.txt 17 | [2019-04-16 15:39:11] INFO [main: CodeCraft-2019.py, 777] preset_answer_path is config/presetAnswer.txt 18 | [2019-04-16 15:39:11] INFO [main: CodeCraft-2019.py, 778] answer_path is config/answer.txt 19 | -------------------------------------------------------------------------------- /result/chusai.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qinguoyi/CodeCraft2019_HUAWEI2019/5a369bbba8234621831419e10c933a97e4557788/result/chusai.jpg -------------------------------------------------------------------------------- /result/fusai.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qinguoyi/CodeCraft2019_HUAWEI2019/5a369bbba8234621831419e10c933a97e4557788/result/fusai.jpg --------------------------------------------------------------------------------