<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>https://neb.kdns.fr/</id>
  <title type="text">星云质心的小破站</title>
  <subtitle type="text">星云浩瀚，质心唯一</subtitle>
  <updated>2023-07-07T00:00:00.000Z</updated>
  <author><name>星云质心</name></author>
  <link rel="alternate" href="https://neb.kdns.fr/"/>
  <link rel="self" href="https://neb.kdns.fr/atom.xml"/>
  <generator uri="https://github.com/CuteLeaf/Firefly">Firefly v6.16.8</generator>
    <entry>
      <id>https://neb.kdns.fr/posts/huawei-control-rush-2023/</id>
      <title type="text">2023 华为嵌入式软件大赛复盘</title>
      <published>2023-07-07T00:00:00.000Z</published>
      <updated>2023-07-07T00:00:00.000Z</updated>
      <author><name>星云质心</name></author>
      <link rel="alternate" href="https://neb.kdns.fr/posts/huawei-control-rush-2023/"/>
      <summary type="text">设计一套算法对光纤部署进行优化，主要解决在光网络中如何在满足多种约束的情况下（放大器约束、通道约束等）合理分配业务传输路径与选择通道，以及扩容光网络时如何合理安排使成本最小。</summary>
      <content type="html"><![CDATA[<section><h2>比赛简介<a href="#比赛简介"><span>#</span></a></h2><section><h3>比赛主页<a href="#比赛主页"><span>#</span></a></h3><p><a href="https://developer.huaweicloud.com/contest/2023controlrush.html" target="_blank">2023 华为嵌入式软件大赛_华为云</a></p></section><section><h3>比赛题目<a href="#比赛题目"><span>#</span></a></h3><p>初赛：设计一套算法对光纤部署进行优化，主要解决在光网络中如何在满足多种约束的情况下（放大器约束、通道约束等）合理分配业务传输路径与选择通道，以及扩容光网络时如何合理安排使成本最小。</p><p>复赛：为了提高光网络的可靠性，部分光业务需要规划多条路径，这些路径同源同宿，但彼此之间不能有相同的边。当光业务的路径数量为 2 时，这两条路径分配的通道必须相同；当光业务的路径数量大于 2 时，这些路径分配的通道可以不同。</p></section></section>
<section><h2>初赛策略<a href="#初赛策略"><span>#</span></a></h2><p>初赛期间主要设计了基本的分配与扩容方案，没有设计迭代优化算法来对已经分配好的光网络进行调整，导致成本不算特别低，只拿到了第三名的成绩。在初赛之后通过自主设计判题器来辅助测试，设计了新的网络迭代优化算法，成功使成本大幅度降低。以下对最终代码中的部分重要算法进行解析。</p><section><h3>存图<a href="#存图"><span>#</span></a></h3><p>采用链式前向星为基础存图方案，便于后续对一个节点出发的边进行遍历。按照赛题每一条边应为双向边，但为了链式前向星本身的特点和兼容性考虑，采用单向边存图，即对于每一条光网络中的边当作两条方向不同的单向边进行储存。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Edge</span><span> {</span></div></div><div><div><div>2</div></div><div><span>public:</span></div></div><div><div><div>3</div></div><div><span>    </span><span>int</span><span> </span><span>from</span><span>, </span><span>to</span><span>, </span><span>d</span><span>, </span><span>next</span><span>;</span><span>    // 起点，终点，边的距离，同起点的下一条边在edge中的编号</span></div></div><div><div><div>4</div></div><div><span>    </span><span>int</span><span> </span><span>trueD</span><span>;</span><span>    // 边的真正距离</span></div></div><div><div><div>5</div></div><div><span>    </span><span>int</span><span> </span><span>Pile</span><span>[</span><span>maxP</span><span>];</span><span> // 该边上存在的通道，记录的是当前承载的业务的编号，不承载业务时值为-1</span></div></div><div><div><div>6</div></div><div><span>    </span><span>int</span><span> </span><span>usedPileCnt</span><span>;</span></div></div><div><div><div>7</div></div><div><span>    </span><span>Edge</span><span>() {</span></div></div><div><div><div>8</div></div><div><span>        </span><span>from</span><span> </span><span>=</span><span> </span><span>-</span><span>1</span><span>;</span></div></div><div><div><div>9</div></div><div><span>        </span><span>to</span><span> </span><span>=</span><span> </span><span>-</span><span>1</span><span>;</span></div></div><div><div><div>10</div></div><div><span>        </span><span>d</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>11</div></div><div><span>        </span><span>next</span><span> </span><span>=</span><span> </span><span>-</span><span>1</span><span>;</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>13</div></div><div><span>}</span><span>edge</span><span>[</span><span>maxM</span><span>];</span><span>    // 边集数组</span></div></div></code></pre><div><div></div><div></div></div></figure></div><blockquote><p>要注意 <code>d</code> 并非边的距离，因为寻路方案分为 Dijkstra 和 BFS，曾经在使用 Dijkstra 来模仿 BFS 来忽略距离进行最少边数搜索的时候将 <code>d</code> 置为 1 来实现，边真正的距离为 <code>trueD</code>。</p></blockquote></section><section><h3>业务寻路<a href="#业务寻路"><span>#</span></a></h3><p>在一开始寻路采用 Dijkstra 算法作为基础来搜寻最短路径，但实际上路径长度对成本的影响不大，如果业务只占用更少的边会对后续其他业务的分配更有利，故应该寻找最少边数。通过将边的 <code>d</code> 置为 1 即可使用 Dijkstra 寻找最少边数路径，后续直接使用 BFS 来实现，每一个使用 BFS 的函数都有对应的使用了 Dijkstra 算法的版本，可能因为遍历顺序的原因采用 <code>d</code> 全为 1 的 Dijkstra 算法进行寻路比采用 BFS 的成本略小，但是使用 BFS 可以使算法整体效率得到较大提升。以下仅说明以 BFS 为基础算法的函数，与之同序号的使用 Dijkstra 为基础算法的函数逻辑与功能均与之一致。</p><p>首先是 <code>BFS3</code>，用于寻找不考虑通道堵塞下的最短路径，就是一个纯粹的、无约束的 BFS 寻路，用于构建最短路径长度表方便后续实际寻路进行比较与判断。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>void</span><span> </span><span>BFS3</span><span>(</span><span>Business</span><span>&amp;</span><span><span> </span><span>bus</span><span>) {</span></span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>    </span><span>int</span><span> </span><span>start</span><span> </span><span>=</span><span> </span><span>bus</span><span>.</span><span>start</span><span>, </span><span>end</span><span> </span><span>=</span><span> </span><span>bus</span><span>.</span><span>end</span><span>;</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>    </span><span>if</span><span> (</span><span>minPathSize</span><span>.</span><span>find</span><span>(</span><span>make_pair</span><span>(</span><span>start</span><span>, </span><span>end</span><span>)) </span><span>!=</span><span> </span><span>minPathSize</span><span>.</span><span>end</span><span>())</span><span>   // 键存在，无需再次查找</span></div></div><div><div><div>6</div></div><div><span>        </span><span>return</span><span>;</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>    </span><span>bus</span><span>.</span><span>trueMinPath</span><span>.</span><span>resize</span><span>(</span><span>N</span><span>, </span><span>-</span><span>1</span><span>);</span></div></div><div><div><div>9</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>i</span><span> </span><span>&lt;</span><span> </span><span>N</span><span>; </span><span>++</span><span>i</span><span>) {</span><span> // 赋初值</span></div></div><div><div><div>10</div></div><div><span>        </span><span>vis1</span><span>[</span><span>i</span><span>] </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>    </span><span>queue</span><span>&lt;</span><span>pair</span><span>&lt;</span><span>int</span><span>, </span><span>int</span><span>&gt;&gt; </span><span>bfsQ</span><span>;</span></div></div><div><div><div>14</div></div><div><span>    </span><span>bfsQ</span><span>.</span><span>push</span><span>(</span><span>make_pair</span><span>(</span><span>start</span><span>, </span><span>0</span><span>));</span></div></div><div><div><div>15</div></div><div><span>    </span><span>vis1</span><span>[</span><span>start</span><span>] </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>16</div></div><div><span>    </span><span>int</span><span> </span><span>s</span><span> </span><span>=</span><span> </span><span>start</span><span>;</span></div></div><div><div><div>17</div></div><div><span>    </span><span>int</span><span> </span><span>curLevel</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>18</div></div><div><span>    </span><span>bool</span><span> </span><span>getOutFlag</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>    </span><span>while</span><span> (</span><span>!</span><span>bfsQ</span><span>.</span><span>empty</span><span>() </span><span>&amp;&amp;</span><span> </span><span>!</span><span>getOutFlag</span><span>) {</span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span>        </span><span>s</span><span> </span><span>=</span><span> </span><span>bfsQ</span><span>.</span><span>front</span><span>().</span><span>first</span><span>;</span></div></div><div><div><div>23</div></div><div><span>        </span><span>curLevel</span><span> </span><span>=</span><span> </span><span>bfsQ</span><span>.</span><span>front</span><span>().</span><span>second</span><span>;</span></div></div><div><div><div>24</div></div><div><span>        </span><span>bfsQ</span><span>.</span><span>pop</span><span>();</span></div></div><div><div><div>25</div></div><div>
</div></div><div><div><div>26</div></div><div><span>        </span><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>head</span><span>[</span><span>s</span><span>]; </span><span>i</span><span> </span><span>!=</span><span> </span><span>-</span><span>1</span><span>; </span><span>i</span><span> </span><span>=</span><span> </span><span>edge</span><span>[</span><span>i</span><span>].</span><span>next</span><span>) {</span></div></div><div><div><div>27</div></div><div><span>            </span><span>int</span><span> </span><span>t</span><span> </span><span>=</span><span> </span><span>edge</span><span>[</span><span>i</span><span>].</span><span>to</span><span>;</span></div></div><div><div><div>28</div></div><div><span>            </span><span>if</span><span> (</span><span>vis1</span><span>[</span><span>t</span><span>])</span></div></div><div><div><div>29</div></div><div><span>                </span><span>continue</span><span>;</span></div></div><div><div><div>30</div></div><div><span>            </span><span>vis1</span><span>[</span><span>t</span><span>] </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>31</div></div><div><span>            </span><span>bus</span><span>.</span><span>trueMinPath</span><span>[</span><span>t</span><span>] </span><span>=</span><span> </span><span>i</span><span>;</span><span>    // 记录下抵达路径点t的边的编号i</span></div></div><div><div><div>32</div></div><div><span>            </span><span>if</span><span> (</span><span>t</span><span> </span><span>==</span><span> </span><span>end</span><span>) {</span></div></div><div><div><div>33</div></div><div><span>                </span><span>getOutFlag</span><span> </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>34</div></div><div><span>                </span><span>s</span><span> </span><span>=</span><span> </span><span>t</span><span>;</span></div></div><div><div><div>35</div></div><div><span>                </span><span>++</span><span>curLevel</span><span>;</span></div></div><div><div><div>36</div></div><div><span>                </span><span>break</span><span>;</span></div></div><div><div><div>37</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>38</div></div><div><span>            </span><span>else</span><span> {</span></div></div><div><div><div>39</div></div><div><span>                </span><span>bfsQ</span><span>.</span><span>push</span><span>(</span><span>make_pair</span><span>(</span><span>t</span><span>, </span><span>curLevel</span><span> </span><span>+</span><span> </span><span>1</span><span>));</span></div></div><div><div><div>40</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>41</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>42</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>43</div></div><div><span>    </span><span>minPathSize</span><span>[</span><span>make_pair</span><span>(</span><span>start</span><span>, </span><span>end</span><span>)] </span><span>=</span><span> </span><span>curLevel</span><span>;</span></div></div><div><div><div>44</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><code>BFS1</code> 用于考虑通道的情况下寻找最少边数路径，基本逻辑是遍历每一条通道，然后使用 BFS 寻路，且在寻路时判断该边该通道是否已经被占用，被占用则该条边不能使用。有两个特殊情况就是如果在寻路之前已经调用过加边的函数，则找到一条路径即立刻跳出寻路，不再遍历其他通道，因为此时因为加了新边有很大概率是通畅的；另一个则是当找到的路径特别长时，放弃这条路径，因为特别长的路径虽然不会直接增加太多成本，但是会让整个网络更加堵塞，不利于全局降低成本。如果遍历完成依然找不到合适的路径，则先执行删边操作调整目前网络中冗余的边然后再执行加边。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>void</span><span> </span><span>BFS1</span><span>(</span><span>Business</span><span>&amp;</span><span><span> </span><span>bus</span><span>, </span></span><span>bool</span><span><span> </span><span>ifLoadNewEdge</span><span>) {</span></span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>    </span><span>int</span><span> </span><span>start</span><span> </span><span>=</span><span> </span><span>bus</span><span>.</span><span>start</span><span>, </span><span>end</span><span> </span><span>=</span><span> </span><span>bus</span><span>.</span><span>end</span><span>, </span><span>p</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>4</div></div><div><span>    </span><span>static</span><span> </span><span>int</span><span> </span><span>addNewEdgeCnt</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span><span>  // 加边次数（不是边数）</span></div></div><div><div><div>5</div></div><div><span>    </span><span>static</span><span> </span><span>int</span><span> </span><span>addNewBus</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span><span>   // 加业务次数</span></div></div><div><div><div>6</div></div><div><span>    </span><span>++</span><span>addNewBus</span><span>;</span></div></div><div><div><div>7</div></div><div><span>    </span><span>bool</span><span> </span><span>findPath</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>8</div></div><div><span>    </span><span>int</span><span> </span><span>minPathDist</span><span> </span><span>=</span><span> </span><span>INF</span><span>;</span></div></div><div><div><div>9</div></div><div><span>    </span><span>int</span><span> </span><span>choosenP</span><span> </span><span>=</span><span> </span><span>-</span><span>1</span><span>;</span></div></div><div><div><div>10</div></div><div><span>    </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>tmpOKPath</span><span>;</span></div></div><div><div><div>11</div></div><div><span>    </span><span>double</span><span> </span><span>maxValue</span><span> </span><span>=</span><span> </span><span>-</span><span>1</span><span>;</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>//调整通道遍历顺序有概率使业务分配得更均匀</span></div></div><div><div><div>14</div></div><div><span>    </span><span>if</span><span> (</span><span>addNewBus</span><span> </span><span>%</span><span> </span><span>2</span><span>)</span></div></div><div><div><div>15</div></div><div><span>        </span><span>p</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>16</div></div><div><span>    </span><span>else</span></div></div><div><div><div>17</div></div><div><span>        </span><span>p</span><span> </span><span>=</span><span> </span><span>P</span><span> </span><span>-</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>    </span><span>while</span><span> (</span><span>true</span><span>) {</span></div></div><div><div><div>20</div></div><div><span>        </span><span>if</span><span> (</span><span>addNewBus</span><span> </span><span>%</span><span> </span><span>2</span><span>) {</span></div></div><div><div><div>21</div></div><div><span>            </span><span>++</span><span>p</span><span>;</span></div></div><div><div><div>22</div></div><div><span>            </span><span>if</span><span> (</span><span>p</span><span> </span><span>&gt;=</span><span> </span><span>P</span><span>)</span></div></div><div><div><div>23</div></div><div><span>                </span><span>break</span><span>;</span></div></div><div><div><div>24</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>25</div></div><div><span>        </span><span>else</span><span> {</span></div></div><div><div><div>26</div></div><div><span>            </span><span>--</span><span>p</span><span>;</span></div></div><div><div><div>27</div></div><div><span>            </span><span>if</span><span> (</span><span>p</span><span> </span><span>&lt;</span><span> </span><span>0</span><span>)</span></div></div><div><div><div>28</div></div><div><span>                </span><span>break</span><span>;</span></div></div><div><div><div>29</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>30</div></div><div>
</div></div><div><div><div>31</div></div><div><span>        </span><span>tmpOKPath</span><span>.</span><span>resize</span><span>(</span><span>N</span><span>, </span><span>-</span><span>1</span><span>);</span></div></div><div><div><div>32</div></div><div><span>        </span><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>i</span><span> </span><span>&lt;</span><span> </span><span>N</span><span>; </span><span>++</span><span>i</span><span>) {</span><span> // 赋初值</span></div></div><div><div><div>33</div></div><div><span>            </span><span>vis1</span><span>[</span><span>i</span><span>] </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>34</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>35</div></div><div><span>        </span><span>queue</span><span>&lt;</span><span>pair</span><span>&lt;</span><span>int</span><span>, </span><span>int</span><span>&gt;&gt; </span><span>bfsQ</span><span>;</span></div></div><div><div><div>36</div></div><div><span><span>        </span></span><span>//queue&lt;Node2&gt; bfsq;</span></div></div><div><div><div>37</div></div><div><span>        </span><span>bfsQ</span><span>.</span><span>push</span><span>(</span><span>make_pair</span><span>(</span><span>start</span><span>, </span><span>0</span><span>));</span></div></div><div><div><div>38</div></div><div><span><span>        </span></span><span>//bfsq.push(Node2(start, 0, 0));</span></div></div><div><div><div>39</div></div><div><span>        </span><span>vis1</span><span>[</span><span>start</span><span>] </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>40</div></div><div><span>        </span><span>int</span><span> </span><span>s</span><span> </span><span>=</span><span> </span><span>start</span><span>;</span></div></div><div><div><div>41</div></div><div><span>        </span><span>int</span><span> </span><span>curLevel</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>42</div></div><div><span><span>        </span></span><span>//int totUsedPileCnt = 0;</span></div></div><div><div><div>43</div></div><div><span>        </span><span>bool</span><span> </span><span>getOutFlag</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>44</div></div><div>
</div></div><div><div><div>45</div></div><div><span>        </span><span>while</span><span> (</span><span>!</span><span>bfsQ</span><span>.</span><span>empty</span><span>() </span><span>&amp;&amp;</span><span> </span><span>!</span><span>getOutFlag</span><span>) {</span></div></div><div><div><div>46</div></div><div>
</div></div><div><div><div>47</div></div><div><span><span>            </span></span><span>//Node2 tmpNode = bfsq.front();</span></div></div><div><div><div>48</div></div><div><span>            </span><span>s</span><span> </span><span>=</span><span> </span><span>bfsQ</span><span>.</span><span>front</span><span>().</span><span>first</span><span>;</span></div></div><div><div><div>49</div></div><div><span><span>            </span></span><span>//s = tmpNode.nodeId;</span></div></div><div><div><div>50</div></div><div><span>            </span><span>curLevel</span><span> </span><span>=</span><span> </span><span>bfsQ</span><span>.</span><span>front</span><span>().</span><span>second</span><span>;</span></div></div><div><div><div>51</div></div><div><span><span>            </span></span><span>//curLevel = tmpNode.curLevel;</span></div></div><div><div><div>52</div></div><div><span><span>            </span></span><span>//totUsedPileCnt = tmpNode.usedPileCnt;</span></div></div><div><div><div>53</div></div><div><span>            </span><span>bfsQ</span><span>.</span><span>pop</span><span>();</span></div></div><div><div><div>54</div></div><div><span><span>            </span></span><span>//bfsq.pop();</span></div></div><div><div><div>55</div></div><div>
</div></div><div><div><div>56</div></div><div><span>            </span><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>head</span><span>[</span><span>s</span><span>]; </span><span>i</span><span> </span><span>!=</span><span> </span><span>-</span><span>1</span><span>; </span><span>i</span><span> </span><span>=</span><span> </span><span>edge</span><span>[</span><span>i</span><span>].</span><span>next</span><span>) {</span></div></div><div><div><div>57</div></div><div>
</div></div><div><div><div>58</div></div><div><span>                </span><span>if</span><span> (</span><span>edge</span><span>[</span><span>i</span><span>].</span><span>Pile</span><span>[</span><span>p</span><span>] </span><span>==</span><span> </span><span>-</span><span>1</span><span>) {</span><span>        // pile未被占用时，才试图走该边</span></div></div><div><div><div>59</div></div><div><span>                    </span><span>int</span><span> </span><span>t</span><span> </span><span>=</span><span> </span><span>edge</span><span>[</span><span>i</span><span>].</span><span>to</span><span>;</span></div></div><div><div><div>60</div></div><div><span>                    </span><span>if</span><span> (</span><span>vis1</span><span>[</span><span>t</span><span>])</span></div></div><div><div><div>61</div></div><div><span>                        </span><span>continue</span><span>;</span></div></div><div><div><div>62</div></div><div><span>                    </span><span>vis1</span><span>[</span><span>t</span><span>] </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>63</div></div><div><span>                    </span><span>tmpOKPath</span><span>[</span><span>t</span><span>] </span><span>=</span><span> </span><span>i</span><span>;</span><span>    // 记录下抵达路径点t的边的编号i</span></div></div><div><div><div>64</div></div><div>
</div></div><div><div><div>65</div></div><div><span>                    </span><span>if</span><span> (</span><span>t</span><span> </span><span>==</span><span> </span><span>end</span><span>) {</span></div></div><div><div><div>66</div></div><div><span>                        </span><span>getOutFlag</span><span> </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>67</div></div><div><span>                        </span><span>s</span><span> </span><span>=</span><span> </span><span>t</span><span>;</span></div></div><div><div><div>68</div></div><div><span>                        </span><span>++</span><span>curLevel</span><span>;</span></div></div><div><div><div>69</div></div><div><span><span>                        </span></span><span>//totUsedPileCnt += edge[i].usedPileCnt;</span></div></div><div><div><div>70</div></div><div><span>                        </span><span>break</span><span>;</span></div></div><div><div><div>71</div></div><div><span><span>                    </span></span><span>}</span></div></div><div><div><div>72</div></div><div><span>                    </span><span>else</span><span> {</span></div></div><div><div><div>73</div></div><div><span>                        </span><span>bfsQ</span><span>.</span><span>push</span><span>(</span><span>make_pair</span><span>(</span><span>t</span><span>, </span><span>curLevel</span><span> </span><span>+</span><span> </span><span>1</span><span>));</span></div></div><div><div><div>74</div></div><div><span><span>                        </span></span><span>//bfsq.push(Node2(t, curLevel + 1, totUsedPileCnt + edge[i].usedPileCnt));</span></div></div><div><div><div>75</div></div><div><span><span>                    </span></span><span>}</span></div></div><div><div><div>76</div></div><div><span><span>                </span></span><span>}</span></div></div><div><div><div>77</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>78</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>79</div></div><div><span>        </span><span>if</span><span> (</span><span>s</span><span> </span><span>==</span><span> </span><span>end</span><span>) {</span></div></div><div><div><div>80</div></div><div>
</div></div><div><div><div>81</div></div><div><span><span>            </span></span><span>//if (minPathSize.find(make_pair(start, end)) == minPathSize.end())   // 键不存在</span></div></div><div><div><div>82</div></div><div><span><span>            </span></span><span>//    minPathSize[make_pair(start, end)] = curLevel;</span></div></div><div><div><div>83</div></div><div><span><span>            </span></span><span>//else if (minPathSize[make_pair(start, end)] &gt; curLevel) {</span></div></div><div><div><div>84</div></div><div><span><span>            </span></span><span>//    minPathSize[make_pair(start, end)] = curLevel;</span></div></div><div><div><div>85</div></div><div><span><span>            </span></span><span>//}</span></div></div><div><div><div>86</div></div><div>
</div></div><div><div><div>87</div></div><div><span>            </span><span>if</span><span> (</span><span>minPathSize</span><span>[</span><span>make_pair</span><span>(</span><span>start</span><span>, </span><span>end</span><span>)] </span><span>*</span><span> </span><span>goodBadGap</span><span> </span><span>&gt;</span><span> </span><span>curLevel</span><span>)</span></div></div><div><div><div>88</div></div><div><span>                </span><span>bus</span><span>.</span><span>isBusWellAllocate</span><span> </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>89</div></div><div><span>            </span><span>else</span></div></div><div><div><div>90</div></div><div><span>                </span><span>bus</span><span>.</span><span>isBusWellAllocate</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>91</div></div><div>
</div></div><div><div><div>92</div></div><div><span>            </span><span>if</span><span> (</span><span>ifLoadNewEdge</span><span>) {</span><span>    // 如果BFS1在调用前已经添加了新边，则可以一遍过</span></div></div><div><div><div>93</div></div><div><span>                </span><span>bus</span><span>.</span><span>pathTmp</span><span> </span><span>=</span><span> </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt;(</span><span>tmpOKPath</span><span>.</span><span>begin</span><span>(), </span><span>tmpOKPath</span><span>.</span><span>end</span><span>());</span></div></div><div><div><div>94</div></div><div><span>                </span><span>choosenP</span><span> </span><span>=</span><span> </span><span>p</span><span>;</span></div></div><div><div><div>95</div></div><div><span>                </span><span>findPath</span><span> </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>96</div></div><div><span>                </span><span>break</span><span>;</span></div></div><div><div><div>97</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>98</div></div><div>
</div></div><div><div><div>99</div></div><div><span>            </span><span>if</span><span> (</span><span>curLevel</span><span> </span><span>&gt;</span><span> </span><span>3</span><span> </span><span>*</span><span> </span><span>minPathSize</span><span>[</span><span>make_pair</span><span>(</span><span>start</span><span>, </span><span>end</span><span>)])</span><span>  // 找到的路径长度太长，宁愿不要</span></div></div><div><div><div>100</div></div><div><span>                </span><span>continue</span><span>;</span></div></div><div><div><div>101</div></div><div>
</div></div><div><div><div>102</div></div><div><span>            </span><span>int</span><span> </span><span>curNode</span><span> </span><span>=</span><span> </span><span>end</span><span>, </span><span>tmpDist</span><span> </span><span>=</span><span> </span><span>curLevel</span><span>;</span></div></div><div><div><div>103</div></div><div><span>            </span><span>if</span><span> (</span><span>tmpDist</span><span> </span><span>&lt;</span><span> </span><span>minPathDist</span><span>) {</span></div></div><div><div><div>104</div></div><div><span>                </span><span>minPathDist</span><span> </span><span>=</span><span> </span><span>tmpDist</span><span>;</span></div></div><div><div><div>105</div></div><div><span>                </span><span>bus</span><span>.</span><span>pathTmp</span><span> </span><span>=</span><span> </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt;(</span><span>tmpOKPath</span><span>.</span><span>begin</span><span>(), </span><span>tmpOKPath</span><span>.</span><span>end</span><span>());</span></div></div><div><div><div>106</div></div><div><span>                </span><span>choosenP</span><span> </span><span>=</span><span> </span><span>p</span><span>;</span></div></div><div><div><div>107</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>108</div></div><div><span>            </span><span>findPath</span><span> </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>109</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>110</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>111</div></div><div><span>    </span><span>if</span><span> (</span><span>findPath</span><span> </span><span>==</span><span> </span><span>false</span><span>) {</span></div></div><div><div><div>112</div></div><div>
</div></div><div><div><div>113</div></div><div><span>        </span><span>if</span><span> (</span><span>ifTryDeleteEdge</span><span>) {</span></div></div><div><div><div>114</div></div><div><span>            </span><span>if</span><span> (</span><span>T</span><span> </span><span>&gt;</span><span> </span><span>3500</span><span> </span><span>&amp;&amp;</span><span> </span><span>T</span><span> </span><span>&lt;=</span><span> </span><span>4000</span><span>) {</span></div></div><div><div><div>115</div></div><div><span>                </span><span>if</span><span> (</span><span>/*++addNewEdgeCnt % 2 == 0 &amp;&amp; */</span><span>(</span><span>bus</span><span>.</span><span>start</span><span> </span><span>!=</span><span> </span><span>buses</span><span>[</span><span>bus</span><span>.</span><span>busId</span><span> </span><span>-</span><span> </span><span>1</span><span>].</span><span>start</span><span> </span><span>||</span><span> </span><span>bus</span><span>.</span><span>end</span><span> </span><span>!=</span><span> </span><span>buses</span><span>[</span><span>bus</span><span>.</span><span>busId</span><span> </span><span>-</span><span> </span><span>1</span><span>].</span><span>end</span><span>))</span></div></div><div><div><div>116</div></div><div><span>                    </span><span>tryDeleteEdge</span><span>();</span></div></div><div><div><div>117</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>118</div></div><div><span>            </span><span>else</span></div></div><div><div><div>119</div></div><div><span>                </span><span>if</span><span> (</span><span>/*++addNewEdgeCnt % 2 == 0 &amp;&amp; */</span><span>(</span><span>bus</span><span>.</span><span>start</span><span> </span><span>!=</span><span> </span><span>buses</span><span>[</span><span>bus</span><span>.</span><span>busId</span><span> </span><span>-</span><span> </span><span>1</span><span>].</span><span>start</span><span> </span><span>||</span><span> </span><span>bus</span><span>.</span><span>end</span><span> </span><span>!=</span><span> </span><span>buses</span><span>[</span><span>bus</span><span>.</span><span>busId</span><span> </span><span>-</span><span> </span><span>1</span><span>].</span><span>end</span><span>))</span></div></div><div><div><div>120</div></div><div><span>                    </span><span>tryDeleteEdge</span><span>();</span></div></div><div><div><div>121</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>122</div></div><div>
</div></div><div><div><div>123</div></div><div><span><span>        </span></span><span>//BFS2(bus);       // 旧的加边策略，一但加边，整个路径都会加，但全局性能是当前最好的</span></div></div><div><div><div>124</div></div><div><span>        </span><span>BFS7</span><span>(</span><span>bus</span><span>);</span><span>       // 新加边策略，只加最短路径上需要进行加边的边</span></div></div><div><div><div>125</div></div><div><span>        </span><span>return</span><span>;</span></div></div><div><div><div>126</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>127</div></div><div>
</div></div><div><div><div>128</div></div><div><span>    </span><span>int</span><span> </span><span>curNode</span><span> </span><span>=</span><span> </span><span>end</span><span>;</span></div></div><div><div><div>129</div></div><div><span>    </span><span>bus</span><span>.</span><span>pileId</span><span> </span><span>=</span><span> </span><span>choosenP</span><span>;</span></div></div><div><div><div>130</div></div><div><span>    </span><span>while</span><span> (</span><span>bus</span><span>.</span><span>pathTmp</span><span>[</span><span>curNode</span><span>] </span><span>!=</span><span> </span><span>-</span><span>1</span><span>) {</span></div></div><div><div><div>131</div></div><div><span>        </span><span>int</span><span> </span><span>edgeId</span><span> </span><span>=</span><span> </span><span>bus</span><span>.</span><span>pathTmp</span><span>[</span><span>curNode</span><span>];</span><span>  // 存储于edge数组中真正的边的Id</span></div></div><div><div><div>132</div></div><div><span>        </span><span>++</span><span>node</span><span>[</span><span>curNode</span><span>].</span><span>passBusCnt</span><span>;</span><span>     // 经过节点的业务数加1</span></div></div><div><div><div>133</div></div><div>
</div></div><div><div><div>134</div></div><div><span>        </span><span>bus</span><span>.</span><span>path</span><span>.</span><span>push_back</span><span>(</span><span>edgeId</span><span> </span><span>/</span><span> </span><span>2</span><span>);</span><span> // edgeId / 2是为了适应题目要求</span></div></div><div><div><div>135</div></div><div><span>        </span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>Pile</span><span>[</span><span>choosenP</span><span>] </span><span>=</span><span> </span><span>bus</span><span>.</span><span>busId</span><span>;</span></div></div><div><div><div>136</div></div><div><span>        </span><span>++</span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>usedPileCnt</span><span>;</span></div></div><div><div><div>137</div></div><div>
</div></div><div><div><div>138</div></div><div><span>        </span><span>if</span><span> (</span><span>edgeId</span><span> </span><span>%</span><span> </span><span>2</span><span>) {</span><span>   // 奇数-1</span></div></div><div><div><div>139</div></div><div><span>            </span><span>edge</span><span>[</span><span>edgeId</span><span> </span><span>-</span><span> </span><span>1</span><span>].</span><span>Pile</span><span>[</span><span>choosenP</span><span>] </span><span>=</span><span> </span><span>bus</span><span>.</span><span>busId</span><span>;</span><span>   // 双向边，两边一起处理</span></div></div><div><div><div>140</div></div><div><span>            </span><span>++</span><span>edge</span><span>[</span><span>edgeId</span><span> </span><span>-</span><span> </span><span>1</span><span>].</span><span>usedPileCnt</span><span>;</span></div></div><div><div><div>141</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>142</div></div><div><span>        </span><span>else</span><span> {</span><span>  // 偶数+1</span></div></div><div><div><div>143</div></div><div><span>            </span><span>edge</span><span>[</span><span>edgeId</span><span> </span><span>+</span><span> </span><span>1</span><span>].</span><span>Pile</span><span>[</span><span>choosenP</span><span>] </span><span>=</span><span> </span><span>bus</span><span>.</span><span>busId</span><span>;</span></div></div><div><div><div>144</div></div><div><span>            </span><span>++</span><span>edge</span><span>[</span><span>edgeId</span><span> </span><span>+</span><span> </span><span>1</span><span>].</span><span>usedPileCnt</span><span>;</span></div></div><div><div><div>145</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>146</div></div><div>
</div></div><div><div><div>147</div></div><div><span>        </span><span>curNode</span><span> </span><span>=</span><span> </span><span>edge</span><span>[</span><span>bus</span><span>.</span><span>pathTmp</span><span>[</span><span>curNode</span><span>]].</span><span>from</span><span>;</span></div></div><div><div><div>148</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>149</div></div><div><span>    </span><span>++</span><span>node</span><span>[</span><span>curNode</span><span>].</span><span>passBusCnt</span><span>;</span><span>     // 经过节点的业务数加1</span></div></div><div><div><div>150</div></div><div><span>    </span><span>reverseArray</span><span>(</span><span>bus</span><span>.</span><span>path</span><span>);</span></div></div><div><div><div>151</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>加边扩容<a href="#加边扩容"><span>#</span></a></h3><p>在业务寻路失败的时候，就需要进行加边操作，加边操作有两个函数，分别是 <code>BFS2</code> 和 <code>BFS7</code>。</p><p><code>BFS2</code> 类似于 <code>BFS3</code>，是一个纯粹的 BFS 无约束寻路，其加边思想为不考虑通道堵塞直接寻找最少边数路径，然后直接对整条路径上的所有原有的边都进行加边操作，然后重新交给 <code>BFS1</code> 进行寻路。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>void</span><span> </span><span>BFS2</span><span>(</span><span>Business</span><span>&amp;</span><span><span> </span><span>bus</span><span>) {</span></span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>    </span><span>int</span><span> </span><span>start</span><span> </span><span>=</span><span> </span><span>bus</span><span>.</span><span>start</span><span>, </span><span>end</span><span> </span><span>=</span><span> </span><span>bus</span><span>.</span><span>end</span><span>;</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>    </span><span>bus</span><span>.</span><span>trueMinPath</span><span>.</span><span>resize</span><span>(</span><span>N</span><span>, </span><span>-</span><span>1</span><span>);</span></div></div><div><div><div>6</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>i</span><span> </span><span>&lt;</span><span> </span><span>N</span><span>; </span><span>++</span><span>i</span><span>) {</span><span> // 赋初值</span></div></div><div><div><div>7</div></div><div><span>        </span><span>vis1</span><span>[</span><span>i</span><span>] </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>    </span><span>queue</span><span>&lt;</span><span>pair</span><span>&lt;</span><span>int</span><span>, </span><span>int</span><span>&gt;&gt; </span><span>bfsQ</span><span>;</span></div></div><div><div><div>11</div></div><div><span>    </span><span>bfsQ</span><span>.</span><span>push</span><span>(</span><span>make_pair</span><span>(</span><span>start</span><span>, </span><span>0</span><span>));</span></div></div><div><div><div>12</div></div><div><span>    </span><span>vis1</span><span>[</span><span>start</span><span>] </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>13</div></div><div><span>    </span><span>int</span><span> </span><span>s</span><span> </span><span>=</span><span> </span><span>start</span><span>;</span></div></div><div><div><div>14</div></div><div><span>    </span><span>int</span><span> </span><span>curLevel</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>15</div></div><div><span>    </span><span>bool</span><span> </span><span>getOutFlag</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span>    </span><span>while</span><span> (</span><span>!</span><span>bfsQ</span><span>.</span><span>empty</span><span>() </span><span>&amp;&amp;</span><span> </span><span>!</span><span>getOutFlag</span><span>) {</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>        </span><span>s</span><span> </span><span>=</span><span> </span><span>bfsQ</span><span>.</span><span>front</span><span>().</span><span>first</span><span>;</span></div></div><div><div><div>20</div></div><div><span>        </span><span>curLevel</span><span> </span><span>=</span><span> </span><span>bfsQ</span><span>.</span><span>front</span><span>().</span><span>second</span><span>;</span></div></div><div><div><div>21</div></div><div><span>        </span><span>bfsQ</span><span>.</span><span>pop</span><span>();</span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span>        </span><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>head</span><span>[</span><span>s</span><span>]; </span><span>i</span><span> </span><span>!=</span><span> </span><span>-</span><span>1</span><span>; </span><span>i</span><span> </span><span>=</span><span> </span><span>edge</span><span>[</span><span>i</span><span>].</span><span>next</span><span>) {</span></div></div><div><div><div>24</div></div><div><span>            </span><span>int</span><span> </span><span>t</span><span> </span><span>=</span><span> </span><span>edge</span><span>[</span><span>i</span><span>].</span><span>to</span><span>;</span></div></div><div><div><div>25</div></div><div><span>            </span><span>if</span><span> (</span><span>vis1</span><span>[</span><span>t</span><span>])</span></div></div><div><div><div>26</div></div><div><span>                </span><span>continue</span><span>;</span></div></div><div><div><div>27</div></div><div><span>            </span><span>vis1</span><span>[</span><span>t</span><span>] </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>28</div></div><div><span>            </span><span>bus</span><span>.</span><span>trueMinPath</span><span>[</span><span>t</span><span>] </span><span>=</span><span> </span><span>i</span><span>;</span><span>    // 记录下抵达路径点t的边的编号i</span></div></div><div><div><div>29</div></div><div><span>            </span><span>if</span><span> (</span><span>t</span><span> </span><span>==</span><span> </span><span>end</span><span>) {</span></div></div><div><div><div>30</div></div><div><span>                </span><span>getOutFlag</span><span> </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>31</div></div><div><span>                </span><span>s</span><span> </span><span>=</span><span> </span><span>t</span><span>;</span></div></div><div><div><div>32</div></div><div><span>                </span><span>break</span><span>;</span></div></div><div><div><div>33</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>34</div></div><div><span>            </span><span>else</span><span> {</span></div></div><div><div><div>35</div></div><div><span>                </span><span>bfsQ</span><span>.</span><span>push</span><span>(</span><span>make_pair</span><span>(</span><span>t</span><span>, </span><span>curLevel</span><span> </span><span>+</span><span> </span><span>1</span><span>));</span></div></div><div><div><div>36</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>37</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>38</div></div><div>
</div></div><div><div><div>39</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>40</div></div><div>
</div></div><div><div><div>41</div></div><div><span>    </span><span>int</span><span> </span><span>curNode</span><span> </span><span>=</span><span> </span><span>end</span><span>;</span></div></div><div><div><div>42</div></div><div><span>    </span><span>while</span><span> (</span><span>bus</span><span>.</span><span>trueMinPath</span><span>[</span><span>curNode</span><span>] </span><span>!=</span><span> </span><span>-</span><span>1</span><span>) {</span></div></div><div><div><div>43</div></div><div><span>        </span><span>int</span><span> </span><span>edgeId</span><span> </span><span>=</span><span> </span><span>bus</span><span>.</span><span>trueMinPath</span><span>[</span><span>curNode</span><span>];</span><span>  // 存储于edge数组中真正的边的Id</span></div></div><div><div><div>44</div></div><div>
</div></div><div><div><div>45</div></div><div><span>        </span><span>addEdge</span><span>(</span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>from</span><span>, </span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>to</span><span>, </span><span>minDist</span><span>[</span><span>make_pair</span><span>(</span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>from</span><span>, </span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>to</span><span>)]);</span></div></div><div><div><div>46</div></div><div><span>        </span><span>addEdge</span><span>(</span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>to</span><span>, </span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>from</span><span>, </span><span>minDist</span><span>[</span><span>make_pair</span><span>(</span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>to</span><span>, </span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>from</span><span>)]);</span></div></div><div><div><div>47</div></div><div>
</div></div><div><div><div>48</div></div><div><span>        </span><span>if</span><span> (</span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>from</span><span> </span><span>&lt;</span><span> </span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>to</span><span>)</span></div></div><div><div><div>49</div></div><div><span>            </span><span>newEdge</span><span>.</span><span>emplace_back</span><span>(</span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>from</span><span>, </span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>to</span><span>);</span></div></div><div><div><div>50</div></div><div><span>        </span><span>else</span></div></div><div><div><div>51</div></div><div><span>            </span><span>newEdge</span><span>.</span><span>emplace_back</span><span>(</span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>to</span><span>, </span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>from</span><span>);</span></div></div><div><div><div>52</div></div><div><span>        </span><span>newEdgePathId</span><span>.</span><span>emplace_back</span><span>(</span><span>cntEdge</span><span> </span><span>/</span><span> </span><span>2</span><span> </span><span>-</span><span> </span><span>1</span><span>);</span></div></div><div><div><div>53</div></div><div>
</div></div><div><div><div>54</div></div><div><span>        </span><span>curNode</span><span> </span><span>=</span><span> </span><span>edge</span><span>[</span><span>bus</span><span>.</span><span>trueMinPath</span><span>[</span><span>curNode</span><span>]].</span><span>from</span><span>;</span></div></div><div><div><div>55</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>56</div></div><div><span>    </span><span>BFS1</span><span>(</span><span>bus</span><span>, </span><span>true</span><span>);</span></div></div><div><div><div>57</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><code>BFS2</code> 是最原始的加边策略，毫无疑问这样的加边策略会导致加很多没有用上的边，从单个业务的效果上来看成本巨大，于是便有了 <code>BFS7</code>。<code>BFS7</code> 的加边思想是先不考虑堵塞寻找最少边数路径，然后在这条路径上搜索所有通道，选择堵塞边数最少的通道，对路径上这个通道堵塞的边进行加边，也就是在不考虑堵塞的最少边数路径上加最少的边。所以虽然 <code>BFS7</code> 加边数少了很多，但其依然不是最少的，因为是先选定了不考虑堵塞的最少边数路径，但是很有可能选择其他路径需要加边的数量会更少。这种加边数最少的策略我也尝试过，但是由于其计算复杂度稍高，且效果并不好（具体原因下面会分析），最终没有应用，此处不做说明。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>void</span><span> </span><span>BFS7</span><span>(</span><span>Business</span><span>&amp;</span><span><span> </span><span>bus</span><span>) {</span></span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>    </span><span>int</span><span> </span><span>start</span><span> </span><span>=</span><span> </span><span>bus</span><span>.</span><span>start</span><span>, </span><span>end</span><span> </span><span>=</span><span> </span><span>bus</span><span>.</span><span>end</span><span>;</span></div></div><div><div><div>4</div></div><div><span>    </span><span>int</span><span> </span><span>minBlockEdge</span><span> </span><span>=</span><span> </span><span>INF</span><span>;</span></div></div><div><div><div>5</div></div><div><span>    </span><span>int</span><span> </span><span>choosenP</span><span> </span><span>=</span><span> </span><span>-</span><span>1</span><span>;</span></div></div><div><div><div>6</div></div><div><span>    </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>tmpOKPath</span><span>;</span></div></div><div><div><div>7</div></div><div><span>    </span><span>tmpOKPath</span><span>.</span><span>resize</span><span>(</span><span>N</span><span>, </span><span>-</span><span>1</span><span>);</span></div></div><div><div><div>8</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>i</span><span> </span><span>&lt;</span><span> </span><span>N</span><span>; </span><span>++</span><span>i</span><span>) {</span><span> // 赋初值</span></div></div><div><div><div>9</div></div><div><span>        </span><span>vis1</span><span>[</span><span>i</span><span>] </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>11</div></div><div><span>    </span><span>queue</span><span>&lt;</span><span>pair</span><span>&lt;</span><span>int</span><span>, </span><span>int</span><span>&gt;&gt; </span><span>bfsQ</span><span>;</span></div></div><div><div><div>12</div></div><div><span>    </span><span>bfsQ</span><span>.</span><span>push</span><span>(</span><span>make_pair</span><span>(</span><span>start</span><span>, </span><span>0</span><span>));</span></div></div><div><div><div>13</div></div><div><span>    </span><span>vis1</span><span>[</span><span>start</span><span>] </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>14</div></div><div><span>    </span><span>int</span><span> </span><span>s</span><span> </span><span>=</span><span> </span><span>start</span><span>;</span></div></div><div><div><div>15</div></div><div><span>    </span><span>int</span><span> </span><span>curLevel</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>16</div></div><div><span>    </span><span>bool</span><span> </span><span>getOutFlag</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>    </span><span>while</span><span> (</span><span>!</span><span>bfsQ</span><span>.</span><span>empty</span><span>() </span><span>&amp;&amp;</span><span> </span><span>!</span><span>getOutFlag</span><span>) {</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>        </span><span>s</span><span> </span><span>=</span><span> </span><span>bfsQ</span><span>.</span><span>front</span><span>().</span><span>first</span><span>;</span></div></div><div><div><div>21</div></div><div><span>        </span><span>curLevel</span><span> </span><span>=</span><span> </span><span>bfsQ</span><span>.</span><span>front</span><span>().</span><span>second</span><span>;</span></div></div><div><div><div>22</div></div><div><span>        </span><span>bfsQ</span><span>.</span><span>pop</span><span>();</span></div></div><div><div><div>23</div></div><div>
</div></div><div><div><div>24</div></div><div><span>        </span><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>head</span><span>[</span><span>s</span><span>]; </span><span>i</span><span> </span><span>!=</span><span> </span><span>-</span><span>1</span><span>; </span><span>i</span><span> </span><span>=</span><span> </span><span>edge</span><span>[</span><span>i</span><span>].</span><span>next</span><span>) {</span></div></div><div><div><div>25</div></div><div>
</div></div><div><div><div>26</div></div><div><span>            </span><span>int</span><span> </span><span>t</span><span> </span><span>=</span><span> </span><span>edge</span><span>[</span><span>i</span><span>].</span><span>to</span><span>;</span></div></div><div><div><div>27</div></div><div><span>            </span><span>if</span><span> (</span><span>vis1</span><span>[</span><span>t</span><span>])</span></div></div><div><div><div>28</div></div><div><span>                </span><span>continue</span><span>;</span></div></div><div><div><div>29</div></div><div><span>            </span><span>vis1</span><span>[</span><span>t</span><span>] </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>30</div></div><div><span>            </span><span>tmpOKPath</span><span>[</span><span>t</span><span>] </span><span>=</span><span> </span><span>i</span><span>;</span><span>    // 记录下抵达路径点t的边的编号i</span></div></div><div><div><div>31</div></div><div>
</div></div><div><div><div>32</div></div><div><span>            </span><span>if</span><span> (</span><span>t</span><span> </span><span>==</span><span> </span><span>end</span><span>) {</span></div></div><div><div><div>33</div></div><div><span>                </span><span>getOutFlag</span><span> </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>34</div></div><div><span>                </span><span>s</span><span> </span><span>=</span><span> </span><span>t</span><span>;</span></div></div><div><div><div>35</div></div><div><span>                </span><span>++</span><span>curLevel</span><span>;</span></div></div><div><div><div>36</div></div><div><span>                </span><span>break</span><span>;</span></div></div><div><div><div>37</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>38</div></div><div><span>            </span><span>else</span></div></div><div><div><div>39</div></div><div><span>                </span><span>bfsQ</span><span>.</span><span>push</span><span>(</span><span>make_pair</span><span>(</span><span>t</span><span>, </span><span>curLevel</span><span> </span><span>+</span><span> </span><span>1</span><span>));</span></div></div><div><div><div>40</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>41</div></div><div>
</div></div><div><div><div>42</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>43</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> </span><span>p</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>p</span><span> </span><span>&lt;</span><span> </span><span>P</span><span>; </span><span>++</span><span>p</span><span>) {</span></div></div><div><div><div>44</div></div><div>
</div></div><div><div><div>45</div></div><div><span>        </span><span>int</span><span> </span><span>curNode</span><span> </span><span>=</span><span> </span><span>end</span><span>, </span><span>tmpBlockEdge</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>46</div></div><div><span>        </span><span>while</span><span> (</span><span>tmpOKPath</span><span>[</span><span>curNode</span><span>] </span><span>!=</span><span> </span><span>-</span><span>1</span><span>) {</span></div></div><div><div><div>47</div></div><div><span>            </span><span>int</span><span> </span><span>edgeId</span><span> </span><span>=</span><span> </span><span>tmpOKPath</span><span>[</span><span>curNode</span><span>];</span><span>  // 存储于edge数组中真正的边的Id</span></div></div><div><div><div>48</div></div><div><span>            </span><span>if</span><span> (</span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>Pile</span><span>[</span><span>p</span><span>] </span><span>!=</span><span> </span><span>-</span><span>1</span><span>)</span></div></div><div><div><div>49</div></div><div><span>                </span><span>++</span><span>tmpBlockEdge</span><span>;</span></div></div><div><div><div>50</div></div><div><span>            </span><span>curNode</span><span> </span><span>=</span><span> </span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>from</span><span>;</span></div></div><div><div><div>51</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>52</div></div><div>
</div></div><div><div><div>53</div></div><div><span>        </span><span>if</span><span> (</span><span>tmpBlockEdge</span><span> </span><span>&lt;</span><span> </span><span>minBlockEdge</span><span>) {</span><span>   // 选需要加边数最少的通道</span></div></div><div><div><div>54</div></div><div><span>            </span><span>minBlockEdge</span><span> </span><span>=</span><span> </span><span>tmpBlockEdge</span><span>;</span></div></div><div><div><div>55</div></div><div><span>            </span><span>bus</span><span>.</span><span>pathTmp</span><span> </span><span>=</span><span> </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt;(</span><span>tmpOKPath</span><span>.</span><span>begin</span><span>(), </span><span>tmpOKPath</span><span>.</span><span>end</span><span>());</span></div></div><div><div><div>56</div></div><div><span>            </span><span>choosenP</span><span> </span><span>=</span><span> </span><span>p</span><span>;</span></div></div><div><div><div>57</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>58</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>59</div></div><div>
</div></div><div><div><div>60</div></div><div><span>    </span><span>int</span><span> </span><span>curNode</span><span> </span><span>=</span><span> </span><span>end</span><span>;</span></div></div><div><div><div>61</div></div><div><span>    </span><span>bus</span><span>.</span><span>pileId</span><span> </span><span>=</span><span> </span><span>choosenP</span><span>;</span></div></div><div><div><div>62</div></div><div><span>    </span><span>while</span><span> (</span><span>bus</span><span>.</span><span>pathTmp</span><span>[</span><span>curNode</span><span>] </span><span>!=</span><span> </span><span>-</span><span>1</span><span>) {</span></div></div><div><div><div>63</div></div><div><span>        </span><span>int</span><span> </span><span>edgeId</span><span> </span><span>=</span><span> </span><span>bus</span><span>.</span><span>pathTmp</span><span>[</span><span>curNode</span><span>];</span><span>  // 存储于edge数组中真正的边的Id</span></div></div><div><div><div>64</div></div><div><span>        </span><span>int</span><span> </span><span>lastNode</span><span> </span><span>=</span><span> </span><span>curNode</span><span>;</span></div></div><div><div><div>65</div></div><div><span>        </span><span>++</span><span>node</span><span>[</span><span>curNode</span><span>].</span><span>passBusCnt</span><span>;</span><span>     // 经过节点的业务数加1</span></div></div><div><div><div>66</div></div><div><span>        </span><span>curNode</span><span> </span><span>=</span><span> </span><span>edge</span><span>[</span><span>bus</span><span>.</span><span>pathTmp</span><span>[</span><span>curNode</span><span>]].</span><span>from</span><span>;</span></div></div><div><div><div>67</div></div><div>
</div></div><div><div><div>68</div></div><div><span>        </span><span>if</span><span> (</span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>Pile</span><span>[</span><span>choosenP</span><span>] </span><span>==</span><span> </span><span>-</span><span>1</span><span>) {</span><span>    // 无需加边</span></div></div><div><div><div>69</div></div><div><span>            </span><span>bus</span><span>.</span><span>path</span><span>.</span><span>push_back</span><span>(</span><span>edgeId</span><span> </span><span>/</span><span> </span><span>2</span><span>);</span><span> // edgeId / 2是为了适应题目要求</span></div></div><div><div><div>70</div></div><div><span>            </span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>Pile</span><span>[</span><span>choosenP</span><span>] </span><span>=</span><span> </span><span>bus</span><span>.</span><span>busId</span><span>;</span></div></div><div><div><div>71</div></div><div><span>            </span><span>++</span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>usedPileCnt</span><span>;</span></div></div><div><div><div>72</div></div><div>
</div></div><div><div><div>73</div></div><div><span>            </span><span>if</span><span> (</span><span>edgeId</span><span> </span><span>%</span><span> </span><span>2</span><span>) {</span><span>   // 奇数-1</span></div></div><div><div><div>74</div></div><div><span>                </span><span>edge</span><span>[</span><span>edgeId</span><span> </span><span>-</span><span> </span><span>1</span><span>].</span><span>Pile</span><span>[</span><span>choosenP</span><span>] </span><span>=</span><span> </span><span>bus</span><span>.</span><span>busId</span><span>;</span><span>   // 双向边，两边一起处理</span></div></div><div><div><div>75</div></div><div><span>                </span><span>++</span><span>edge</span><span>[</span><span>edgeId</span><span> </span><span>-</span><span> </span><span>1</span><span>].</span><span>usedPileCnt</span><span>;</span></div></div><div><div><div>76</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>77</div></div><div><span>            </span><span>else</span><span> {</span><span>  // 偶数+1</span></div></div><div><div><div>78</div></div><div><span>                </span><span>edge</span><span>[</span><span>edgeId</span><span> </span><span>+</span><span> </span><span>1</span><span>].</span><span>Pile</span><span>[</span><span>choosenP</span><span>] </span><span>=</span><span> </span><span>bus</span><span>.</span><span>busId</span><span>;</span></div></div><div><div><div>79</div></div><div><span>                </span><span>++</span><span>edge</span><span>[</span><span>edgeId</span><span> </span><span>+</span><span> </span><span>1</span><span>].</span><span>usedPileCnt</span><span>;</span></div></div><div><div><div>80</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>81</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>82</div></div><div><span>        </span><span>else</span><span> {</span><span>      // 需要加边</span></div></div><div><div><div>83</div></div><div><span>            </span><span>addEdge</span><span>(</span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>from</span><span>, </span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>to</span><span>, </span><span>minDist</span><span>[</span><span>make_pair</span><span>(</span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>from</span><span>, </span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>to</span><span>)]);</span></div></div><div><div><div>84</div></div><div><span>            </span><span>addEdge</span><span>(</span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>to</span><span>, </span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>from</span><span>, </span><span>minDist</span><span>[</span><span>make_pair</span><span>(</span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>to</span><span>, </span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>from</span><span>)]);</span></div></div><div><div><div>85</div></div><div>
</div></div><div><div><div>86</div></div><div><span>            </span><span>if</span><span> (</span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>from</span><span> </span><span>&lt;</span><span> </span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>to</span><span>)</span></div></div><div><div><div>87</div></div><div><span>                </span><span>newEdge</span><span>.</span><span>emplace_back</span><span>(</span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>from</span><span>, </span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>to</span><span>);</span></div></div><div><div><div>88</div></div><div><span>            </span><span>else</span></div></div><div><div><div>89</div></div><div><span>                </span><span>newEdge</span><span>.</span><span>emplace_back</span><span>(</span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>to</span><span>, </span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>from</span><span>);</span></div></div><div><div><div>90</div></div><div><span>            </span><span>newEdgePathId</span><span>.</span><span>emplace_back</span><span>(</span><span>cntEdge</span><span> </span><span>/</span><span> </span><span>2</span><span> </span><span>-</span><span> </span><span>1</span><span>);</span></div></div><div><div><div>91</div></div><div>
</div></div><div><div><div>92</div></div><div><span>            </span><span>bus</span><span>.</span><span>path</span><span>.</span><span>push_back</span><span>(</span><span>cntEdge</span><span> </span><span>/</span><span> </span><span>2</span><span> </span><span>-</span><span> </span><span>1</span><span>);</span><span> // edgeId / 2是为了适应题目要求</span></div></div><div><div><div>93</div></div><div><span>            </span><span>edge</span><span>[</span><span>cntEdge</span><span> </span><span>-</span><span> </span><span>2</span><span>].</span><span>Pile</span><span>[</span><span>choosenP</span><span>] </span><span>=</span><span> </span><span>bus</span><span>.</span><span>busId</span><span>;</span></div></div><div><div><div>94</div></div><div><span>            </span><span>++</span><span>edge</span><span>[</span><span>cntEdge</span><span> </span><span>-</span><span> </span><span>2</span><span>].</span><span>usedPileCnt</span><span>;</span></div></div><div><div><div>95</div></div><div><span>            </span><span>edge</span><span>[</span><span>cntEdge</span><span> </span><span>-</span><span> </span><span>1</span><span>].</span><span>Pile</span><span>[</span><span>choosenP</span><span>] </span><span>=</span><span> </span><span>bus</span><span>.</span><span>busId</span><span>;</span><span>   // 偶数+1</span></div></div><div><div><div>96</div></div><div><span>            </span><span>++</span><span>edge</span><span>[</span><span>cntEdge</span><span> </span><span>-</span><span> </span><span>1</span><span>].</span><span>usedPileCnt</span><span>;</span></div></div><div><div><div>97</div></div><div><span>            </span><span>bus</span><span>.</span><span>pathTmp</span><span>[</span><span>lastNode</span><span>] </span><span>=</span><span> </span><span>cntEdge</span><span> </span><span>-</span><span> </span><span>2</span><span>;</span></div></div><div><div><div>98</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>99</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>100</div></div><div><span>    </span><span>++</span><span>node</span><span>[</span><span>curNode</span><span>].</span><span>passBusCnt</span><span>;</span><span>     // 经过节点的业务数加1</span></div></div><div><div><div>101</div></div><div><span>    </span><span>reverseArray</span><span>(</span><span>bus</span><span>.</span><span>path</span><span>);</span></div></div><div><div><div>102</div></div><div><span>    </span><span>bus</span><span>.</span><span>isBusWellAllocate</span><span> </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>103</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>在 <code>BFS2</code> 与 <code>BFS7</code> 两种加边策略之间，我们最终选择了 <code>BFS2</code>。因为虽然 <code>BFS7</code> 加边数量比 <code>BFS2</code> 少，但是这只是对一个业务而言，我们的总体目标是让全局成本最低，<code>BFS2</code> 虽然对一个业务加的边多了，但是多加的边能在一定程度上缓解网络的堵塞情况，便于后续业务的分配，上文所说到的加边数量最少的算法效果不好也是因为这个原因。再加之 <code>BFS2</code> 虽然加边数量多了，但后续还有删除冗余边和迭代优化分配的算法对网络进行调整，最终并不会存在太多多余的边。实际测试结果也说明了这个问题，<code>BFS2</code> 的全局性能确实是最好的。</p></section><section><h3>删除冗余边<a href="#删除冗余边"><span>#</span></a></h3><p>删除冗余边是降低成本的一个重要部分，其主要思想是统计新增的边上承载的业务数量，若没有承载业务就直接删除；若承载了业务就先保存这条边上的业务的路径，然后对这些业务进行重新分配（这也是后续迭代优化的基本思想），重新分配时不走正在考察这条边，看看能否不使用这条边把原本在这条边上的业务全部分配完成，若可以，则证明这条边为冗余边，可以删除，若不可以，则用保存的原路径复原重新分配寻路时造成的影响。</p><p>重新分配采用 <code>BFS5</code>，类似于 <code>BFS1</code>，区别在于 <code>BFS5</code> 不会触发加边操作，如果找不到符合要求的路径会直接返回 <code>false</code>，标志该业务确实要依赖这条新增的边，即这条边不可以删除。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>bool</span><span> </span><span>BFS5</span><span>(</span><span>Business</span><span>&amp;</span><span><span> </span><span>bus</span><span>, </span></span><span>int</span><span><span> </span><span>blockEdge</span><span>) {</span></span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>    </span><span>int</span><span> </span><span>start</span><span> </span><span>=</span><span> </span><span>bus</span><span>.</span><span>start</span><span>, </span><span>end</span><span> </span><span>=</span><span> </span><span>bus</span><span>.</span><span>end</span><span>, </span><span>p</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>    </span><span>bool</span><span> </span><span>findPath</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>6</div></div><div><span>    </span><span>int</span><span> </span><span>minPathDist</span><span> </span><span>=</span><span> </span><span>INF</span><span>;</span></div></div><div><div><div>7</div></div><div><span>    </span><span>int</span><span> </span><span>choosenP</span><span> </span><span>=</span><span> </span><span>-</span><span>1</span><span>;</span></div></div><div><div><div>8</div></div><div><span>    </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>tmpOKPath</span><span>;</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>    </span><span>for</span><span> (; </span><span>p</span><span> </span><span>&lt;</span><span> </span><span>P</span><span>; </span><span>++</span><span>p</span><span>) {</span></div></div><div><div><div>11</div></div><div><span>        </span><span>tmpOKPath</span><span>.</span><span>resize</span><span>(</span><span>N</span><span>, </span><span>-</span><span>1</span><span>);</span></div></div><div><div><div>12</div></div><div><span>        </span><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>i</span><span> </span><span>&lt;</span><span> </span><span>N</span><span>; </span><span>++</span><span>i</span><span>) {</span><span> // 赋初值</span></div></div><div><div><div>13</div></div><div><span>            </span><span>vis1</span><span>[</span><span>i</span><span>] </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>14</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>15</div></div><div><span>        </span><span>queue</span><span>&lt;</span><span>pair</span><span>&lt;</span><span>int</span><span>, </span><span>int</span><span>&gt;&gt; </span><span>bfsQ</span><span>;</span></div></div><div><div><div>16</div></div><div><span>        </span><span>bfsQ</span><span>.</span><span>push</span><span>(</span><span>make_pair</span><span>(</span><span>start</span><span>, </span><span>0</span><span>));</span></div></div><div><div><div>17</div></div><div><span>        </span><span>vis1</span><span>[</span><span>start</span><span>] </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>18</div></div><div><span>        </span><span>int</span><span> </span><span>s</span><span> </span><span>=</span><span> </span><span>start</span><span>;</span></div></div><div><div><div>19</div></div><div><span>        </span><span>int</span><span> </span><span>curLevel</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>20</div></div><div><span>        </span><span>bool</span><span> </span><span>getOutFlag</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span>        </span><span>while</span><span> (</span><span>!</span><span>bfsQ</span><span>.</span><span>empty</span><span>() </span><span>&amp;&amp;</span><span> </span><span>!</span><span>getOutFlag</span><span>) {</span></div></div><div><div><div>23</div></div><div>
</div></div><div><div><div>24</div></div><div><span>            </span><span>s</span><span> </span><span>=</span><span> </span><span>bfsQ</span><span>.</span><span>front</span><span>().</span><span>first</span><span>;</span></div></div><div><div><div>25</div></div><div><span>            </span><span>curLevel</span><span> </span><span>=</span><span> </span><span>bfsQ</span><span>.</span><span>front</span><span>().</span><span>second</span><span>;</span></div></div><div><div><div>26</div></div><div><span>            </span><span>bfsQ</span><span>.</span><span>pop</span><span>();</span></div></div><div><div><div>27</div></div><div>
</div></div><div><div><div>28</div></div><div><span>            </span><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>head</span><span>[</span><span>s</span><span>]; </span><span>i</span><span> </span><span>!=</span><span> </span><span>-</span><span>1</span><span>; </span><span>i</span><span> </span><span>=</span><span> </span><span>edge</span><span>[</span><span>i</span><span>].</span><span>next</span><span>) {</span></div></div><div><div><div>29</div></div><div>
</div></div><div><div><div>30</div></div><div><span>                </span><span>if</span><span> (</span><span>i</span><span> </span><span>/</span><span> </span><span>2</span><span> </span><span>==</span><span> </span><span>blockEdge</span><span>)</span></div></div><div><div><div>31</div></div><div><span>                    </span><span>continue</span><span>;</span></div></div><div><div><div>32</div></div><div>
</div></div><div><div><div>33</div></div><div><span>                </span><span>if</span><span> (</span><span>edge</span><span>[</span><span>i</span><span>].</span><span>Pile</span><span>[</span><span>p</span><span>] </span><span>==</span><span> </span><span>-</span><span>1</span><span>) {</span><span>        // pile未被占用时，才试图走该边</span></div></div><div><div><div>34</div></div><div><span>                    </span><span>int</span><span> </span><span>t</span><span> </span><span>=</span><span> </span><span>edge</span><span>[</span><span>i</span><span>].</span><span>to</span><span>;</span></div></div><div><div><div>35</div></div><div><span>                    </span><span>if</span><span> (</span><span>vis1</span><span>[</span><span>t</span><span>])</span></div></div><div><div><div>36</div></div><div><span>                        </span><span>continue</span><span>;</span></div></div><div><div><div>37</div></div><div><span>                    </span><span>vis1</span><span>[</span><span>t</span><span>] </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>38</div></div><div><span>                    </span><span>tmpOKPath</span><span>[</span><span>t</span><span>] </span><span>=</span><span> </span><span>i</span><span>;</span><span>    // 记录下抵达路径点t的边的编号i</span></div></div><div><div><div>39</div></div><div>
</div></div><div><div><div>40</div></div><div><span>                    </span><span>if</span><span> (</span><span>t</span><span> </span><span>==</span><span> </span><span>end</span><span>) {</span></div></div><div><div><div>41</div></div><div><span>                        </span><span>getOutFlag</span><span> </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>42</div></div><div><span>                        </span><span>s</span><span> </span><span>=</span><span> </span><span>t</span><span>;</span></div></div><div><div><div>43</div></div><div><span>                        </span><span>++</span><span>curLevel</span><span>;</span></div></div><div><div><div>44</div></div><div><span>                        </span><span>break</span><span>;</span></div></div><div><div><div>45</div></div><div><span><span>                    </span></span><span>}</span></div></div><div><div><div>46</div></div><div><span>                    </span><span>else</span><span> {</span></div></div><div><div><div>47</div></div><div><span>                        </span><span>bfsQ</span><span>.</span><span>push</span><span>(</span><span>make_pair</span><span>(</span><span>t</span><span>, </span><span>curLevel</span><span> </span><span>+</span><span> </span><span>1</span><span>));</span></div></div><div><div><div>48</div></div><div><span><span>                    </span></span><span>}</span></div></div><div><div><div>49</div></div><div><span><span>                </span></span><span>}</span></div></div><div><div><div>50</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>51</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>52</div></div><div><span>        </span><span>if</span><span> (</span><span>s</span><span> </span><span>==</span><span> </span><span>end</span><span>) {</span></div></div><div><div><div>53</div></div><div>
</div></div><div><div><div>54</div></div><div><span><span>            </span></span><span>// 找到的路径长度太长，宁愿不要</span></div></div><div><div><div>55</div></div><div><span>            </span><span>if</span><span> (</span><span>!</span><span>ifLast</span><span> </span><span>&amp;&amp;</span><span> (</span><span>curLevel</span><span> </span><span>&gt;</span><span> </span><span>3</span><span> </span><span>*</span><span> </span><span>minPathSize</span><span>[</span><span>make_pair</span><span>(</span><span>start</span><span>, </span><span>end</span><span>)]))</span></div></div><div><div><div>56</div></div><div><span>                </span><span>continue</span><span>;</span></div></div><div><div><div>57</div></div><div>
</div></div><div><div><div>58</div></div><div><span>            </span><span>if</span><span> (</span><span>minPathSize</span><span>[</span><span>make_pair</span><span>(</span><span>start</span><span>, </span><span>end</span><span>)] </span><span>==</span><span> </span><span>curLevel</span><span>)</span></div></div><div><div><div>59</div></div><div><span>                </span><span>bus</span><span>.</span><span>isBusWellAllocate</span><span> </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>60</div></div><div><span>            </span><span>else</span></div></div><div><div><div>61</div></div><div><span>                </span><span>bus</span><span>.</span><span>isBusWellAllocate</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>62</div></div><div>
</div></div><div><div><div>63</div></div><div><span>            </span><span>int</span><span> </span><span>curNode</span><span> </span><span>=</span><span> </span><span>end</span><span>, </span><span>tmpDist</span><span> </span><span>=</span><span> </span><span>curLevel</span><span>;</span></div></div><div><div><div>64</div></div><div><span>            </span><span>if</span><span> (</span><span>tmpDist</span><span> </span><span>&lt;=</span><span> </span><span>minPathDist</span><span>) {</span></div></div><div><div><div>65</div></div><div><span>                </span><span>minPathDist</span><span> </span><span>=</span><span> </span><span>tmpDist</span><span>;</span></div></div><div><div><div>66</div></div><div><span>                </span><span>bus</span><span>.</span><span>pathTmp</span><span> </span><span>=</span><span> </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt;(</span><span>tmpOKPath</span><span>.</span><span>begin</span><span>(), </span><span>tmpOKPath</span><span>.</span><span>end</span><span>());</span></div></div><div><div><div>67</div></div><div><span>                </span><span>choosenP</span><span> </span><span>=</span><span> </span><span>p</span><span>;</span></div></div><div><div><div>68</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>69</div></div><div><span>            </span><span>findPath</span><span> </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>70</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>71</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>72</div></div><div><span>    </span><span>if</span><span> (</span><span>findPath</span><span> </span><span>==</span><span> </span><span>false</span><span>) {</span><span>    // 找不到路，需要构造新边</span></div></div><div><div><div>73</div></div><div><span>        </span><span>return</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>74</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>75</div></div><div>
</div></div><div><div><div>76</div></div><div><span>    </span><span>int</span><span> </span><span>curNode</span><span> </span><span>=</span><span> </span><span>end</span><span>;</span></div></div><div><div><div>77</div></div><div><span>    </span><span>bus</span><span>.</span><span>pileId</span><span> </span><span>=</span><span> </span><span>choosenP</span><span>;</span></div></div><div><div><div>78</div></div><div><span>    </span><span>while</span><span> (</span><span>bus</span><span>.</span><span>pathTmp</span><span>[</span><span>curNode</span><span>] </span><span>!=</span><span> </span><span>-</span><span>1</span><span>) {</span></div></div><div><div><div>79</div></div><div><span>        </span><span>int</span><span> </span><span>edgeId</span><span> </span><span>=</span><span> </span><span>bus</span><span>.</span><span>pathTmp</span><span>[</span><span>curNode</span><span>];</span><span>  // 存储于edge数组中真正的边的Id</span></div></div><div><div><div>80</div></div><div><span>        </span><span>++</span><span>node</span><span>[</span><span>curNode</span><span>].</span><span>passBusCnt</span><span>;</span><span>     // 经过节点的业务数加1</span></div></div><div><div><div>81</div></div><div>
</div></div><div><div><div>82</div></div><div><span>        </span><span>bus</span><span>.</span><span>path</span><span>.</span><span>push_back</span><span>(</span><span>edgeId</span><span> </span><span>/</span><span> </span><span>2</span><span>);</span><span> // edgeId / 2是为了适应题目要求</span></div></div><div><div><div>83</div></div><div><span>        </span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>Pile</span><span>[</span><span>choosenP</span><span>] </span><span>=</span><span> </span><span>bus</span><span>.</span><span>busId</span><span>;</span></div></div><div><div><div>84</div></div><div><span>        </span><span>++</span><span>edge</span><span>[</span><span>edgeId</span><span>].</span><span>usedPileCnt</span><span>;</span></div></div><div><div><div>85</div></div><div>
</div></div><div><div><div>86</div></div><div><span>        </span><span>if</span><span> (</span><span>edgeId</span><span> </span><span>%</span><span> </span><span>2</span><span>) {</span><span>   // 奇数-1</span></div></div><div><div><div>87</div></div><div><span>            </span><span>edge</span><span>[</span><span>edgeId</span><span> </span><span>-</span><span> </span><span>1</span><span>].</span><span>Pile</span><span>[</span><span>choosenP</span><span>] </span><span>=</span><span> </span><span>bus</span><span>.</span><span>busId</span><span>;</span><span>   // 双向边，两边一起处理</span></div></div><div><div><div>88</div></div><div><span>            </span><span>++</span><span>edge</span><span>[</span><span>edgeId</span><span> </span><span>-</span><span> </span><span>1</span><span>].</span><span>usedPileCnt</span><span>;</span></div></div><div><div><div>89</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>90</div></div><div><span>        </span><span>else</span><span> {</span><span>  // 偶数+1</span></div></div><div><div><div>91</div></div><div><span>            </span><span>edge</span><span>[</span><span>edgeId</span><span> </span><span>+</span><span> </span><span>1</span><span>].</span><span>Pile</span><span>[</span><span>choosenP</span><span>] </span><span>=</span><span> </span><span>bus</span><span>.</span><span>busId</span><span>;</span></div></div><div><div><div>92</div></div><div><span>            </span><span>++</span><span>edge</span><span>[</span><span>edgeId</span><span> </span><span>+</span><span> </span><span>1</span><span>].</span><span>usedPileCnt</span><span>;</span></div></div><div><div><div>93</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>94</div></div><div>
</div></div><div><div><div>95</div></div><div><span>        </span><span>curNode</span><span> </span><span>=</span><span> </span><span>edge</span><span>[</span><span>bus</span><span>.</span><span>pathTmp</span><span>[</span><span>curNode</span><span>]].</span><span>from</span><span>;</span></div></div><div><div><div>96</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>97</div></div><div><span>    </span><span>++</span><span>node</span><span>[</span><span>curNode</span><span>].</span><span>passBusCnt</span><span>;</span><span>     // 经过节点的业务数加1</span></div></div><div><div><div>98</div></div><div><span>    </span><span>reverseArray</span><span>(</span><span>bus</span><span>.</span><span>path</span><span>);</span></div></div><div><div><div>99</div></div><div><span>    </span><span>return</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>100</div></div><div><span>}</span></div></div><div><div><div>101</div></div><div>
</div></div><div><div><div>102</div></div><div><span>void</span><span> </span><span>tryDeleteEdge</span><span>() {</span></div></div><div><div><div>103</div></div><div>
</div></div><div><div><div>104</div></div><div><span>    </span><span>int</span><span> </span><span>n</span><span> </span><span>=</span><span> </span><span>newEdge</span><span>.</span><span>size</span><span>(), </span><span>trueEdgeId</span><span>;</span></div></div><div><div><div>105</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> </span><span>idx</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>idx</span><span> </span><span>&lt;</span><span> </span><span>n</span><span>; </span><span>++</span><span>idx</span><span>) {</span></div></div><div><div><div>106</div></div><div><span>        </span><span>int</span><span> </span><span>idxEdge</span><span> </span><span>=</span><span> </span><span>newEdgePathId</span><span>[</span><span>idx</span><span>];</span><span> // idxEdge为边在边集数组的编号（计数时，双向边视作同一边）</span></div></div><div><div><div>107</div></div><div>
</div></div><div><div><div>108</div></div><div><span>        </span><span>trueEdgeId</span><span> </span><span>=</span><span> </span><span>idxEdge</span><span> </span><span>*</span><span> </span><span>2</span><span>;</span></div></div><div><div><div>109</div></div><div><span>        </span><span>int</span><span> </span><span>busCnt</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span><span>     // 记录边上承载的业务数</span></div></div><div><div><div>110</div></div><div><span>        </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>lastBusIds</span><span>, </span><span>lastPileIds</span><span>;</span></div></div><div><div><div>111</div></div><div>
</div></div><div><div><div>112</div></div><div><span>        </span><span>for</span><span> (</span><span>int</span><span> </span><span>j</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>j</span><span> </span><span>&lt;</span><span> </span><span>P</span><span>; </span><span>++</span><span>j</span><span>)</span></div></div><div><div><div>113</div></div><div><span>            </span><span>if</span><span> (</span><span>edge</span><span>[</span><span>trueEdgeId</span><span>].</span><span>Pile</span><span>[</span><span>j</span><span>] </span><span>!=</span><span> </span><span>-</span><span>1</span><span> </span><span>&amp;&amp;</span><span> </span><span>edge</span><span>[</span><span>trueEdgeId</span><span>].</span><span>Pile</span><span>[</span><span>j</span><span>] </span><span>!=</span><span> </span><span>T</span><span>) {</span><span>   // 说明在通道j上承载了该业务</span></div></div><div><div><div>114</div></div><div><span>                </span><span>++</span><span>busCnt</span><span>;</span></div></div><div><div><div>115</div></div><div><span>                </span><span>lastBusIds</span><span>.</span><span>push_back</span><span>(</span><span>edge</span><span>[</span><span>trueEdgeId</span><span>].</span><span>Pile</span><span>[</span><span>j</span><span>]);</span></div></div><div><div><div>116</div></div><div><span>                </span><span>lastPileIds</span><span>.</span><span>push_back</span><span>(</span><span>j</span><span>);</span></div></div><div><div><div>117</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>118</div></div><div>
</div></div><div><div><div>119</div></div><div><span>        </span><span>if</span><span> (</span><span>busCnt</span><span> </span><span>==</span><span> </span><span>0</span><span>) {</span><span>      // 如果该新边上，一条业务都没有承载，直接删边</span></div></div><div><div><div>120</div></div><div>
</div></div><div><div><div>121</div></div><div><span>            </span><span>int</span><span> </span><span>iter</span><span> </span><span>=</span><span> </span><span>find</span><span>(</span><span>newEdgePathId</span><span>.</span><span>begin</span><span>(), </span><span>newEdgePathId</span><span>.</span><span>end</span><span>(), </span><span>idxEdge</span><span>) </span><span>-</span><span> </span><span>newEdgePathId</span><span>.</span><span>begin</span><span>();</span></div></div><div><div><div>122</div></div><div><span>            </span><span>newEdge</span><span>.</span><span>erase</span><span>(</span><span>newEdge</span><span>.</span><span>begin</span><span>() </span><span>+</span><span> </span><span>iter</span><span>);</span></div></div><div><div><div>123</div></div><div><span>            </span><span>newEdgePathId</span><span>.</span><span>erase</span><span>(</span><span>newEdgePathId</span><span>.</span><span>begin</span><span>() </span><span>+</span><span> </span><span>iter</span><span>);</span></div></div><div><div><div>124</div></div><div><span>            </span><span>--</span><span>idx</span><span>;</span></div></div><div><div><div>125</div></div><div><span>            </span><span>--</span><span>n</span><span>;</span></div></div><div><div><div>126</div></div><div>
</div></div><div><div><div>127</div></div><div><span>            </span><span>for</span><span> (</span><span>int</span><span> </span><span>k</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>k</span><span> </span><span>&lt;</span><span> </span><span>P</span><span>; </span><span>++</span><span>k</span><span>) {</span><span>   // 该边已删除，就应对其进行封锁</span></div></div><div><div><div>128</div></div><div><span>                </span><span>edge</span><span>[</span><span>trueEdgeId</span><span>].</span><span>Pile</span><span>[</span><span>k</span><span>] </span><span>=</span><span> </span><span>T</span><span>;</span></div></div><div><div><div>129</div></div><div><span>                </span><span>edge</span><span>[</span><span>trueEdgeId</span><span> </span><span>+</span><span> </span><span>1</span><span>].</span><span>Pile</span><span>[</span><span>k</span><span>] </span><span>=</span><span> </span><span>T</span><span>;</span><span>   // 偶数+1</span></div></div><div><div><div>130</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>131</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>132</div></div><div><span>        </span><span>else</span><span> {</span><span>  // 如果该新边上，承载了多条业务，则对该边上的所有业务重新分配，看能否不依赖该新边</span></div></div><div><div><div>133</div></div><div>
</div></div><div><div><div>134</div></div><div><span>            </span><span>vector</span><span>&lt;</span><span>vector</span><span>&lt;</span><span>int</span><span>&gt;&gt; </span><span>pathTmp</span><span>(</span><span>busCnt</span><span>, </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt;());</span><span>     // 用于此后重新加载边</span></div></div><div><div><div>135</div></div><div><span>            </span><span>for</span><span> (</span><span>int</span><span> </span><span>k</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>k</span><span> </span><span>&lt;</span><span> </span><span>busCnt</span><span>; </span><span>++</span><span>k</span><span>) {</span></div></div><div><div><div>136</div></div><div><span>                </span><span>pathTmp</span><span>[</span><span>k</span><span>] </span><span>=</span><span> </span><span>buses</span><span>[</span><span>lastBusIds</span><span>[</span><span>k</span><span>]].</span><span>pathTmp</span><span>;</span></div></div><div><div><div>137</div></div><div><span>                </span><span>reCoverNetwork</span><span>(</span><span>lastBusIds</span><span>[</span><span>k</span><span>], </span><span>lastPileIds</span><span>[</span><span>k</span><span>]);</span></div></div><div><div><div>138</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>139</div></div><div>
</div></div><div><div><div>140</div></div><div><span>            </span><span>bool</span><span> </span><span>findPath</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>141</div></div><div><span>            </span><span>int</span><span> </span><span>stopK</span><span> </span><span>=</span><span> </span><span>-</span><span>1</span><span>;</span></div></div><div><div><div>142</div></div><div><span>            </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>tmpLastPileIds</span><span>;</span></div></div><div><div><div>143</div></div><div><span>            </span><span>for</span><span> (</span><span>int</span><span> </span><span>k</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>k</span><span> </span><span>&lt;</span><span> </span><span>busCnt</span><span>; </span><span>++</span><span>k</span><span>) {</span></div></div><div><div><div>144</div></div><div>
</div></div><div><div><div>145</div></div><div><span>                </span><span>findPath</span><span> </span><span>=</span><span> </span><span>BFS5</span><span>(</span><span>buses</span><span>[</span><span>lastBusIds</span><span>[</span><span>k</span><span>]], </span><span>idxEdge</span><span>);</span></div></div><div><div><div>146</div></div><div><span><span>                </span></span><span>//findPath = dijkstra5(buses[lastBusIds[k]], idxEdge);</span></div></div><div><div><div>147</div></div><div>
</div></div><div><div><div>148</div></div><div><span>                </span><span>if</span><span> (</span><span>findPath</span><span> </span><span>==</span><span> </span><span>false</span><span>) {</span></div></div><div><div><div>149</div></div><div><span>                    </span><span>stopK</span><span> </span><span>=</span><span> </span><span>k</span><span>;</span></div></div><div><div><div>150</div></div><div><span>                    </span><span>break</span><span>;</span></div></div><div><div><div>151</div></div><div><span><span>                </span></span><span>}</span></div></div><div><div><div>152</div></div><div><span>                </span><span>tmpLastPileIds</span><span>.</span><span>push_back</span><span>(</span><span>buses</span><span>[</span><span>lastBusIds</span><span>[</span><span>k</span><span>]].</span><span>pileId</span><span>);</span><span>   // 原本的pileId已改变，此处进行更新，以防止reCoverNetwork时出bug</span></div></div><div><div><div>153</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>154</div></div><div>
</div></div><div><div><div>155</div></div><div><span>            </span><span>if</span><span> (</span><span>findPath</span><span>) {</span></div></div><div><div><div>156</div></div><div>
</div></div><div><div><div>157</div></div><div><span>                </span><span>int</span><span> </span><span>iter</span><span> </span><span>=</span><span> </span><span>find</span><span>(</span><span>newEdgePathId</span><span>.</span><span>begin</span><span>(), </span><span>newEdgePathId</span><span>.</span><span>end</span><span>(), </span><span>idxEdge</span><span>) </span><span>-</span><span> </span><span>newEdgePathId</span><span>.</span><span>begin</span><span>();</span></div></div><div><div><div>158</div></div><div><span>                </span><span>newEdge</span><span>.</span><span>erase</span><span>(</span><span>newEdge</span><span>.</span><span>begin</span><span>() </span><span>+</span><span> </span><span>iter</span><span>);</span></div></div><div><div><div>159</div></div><div><span>                </span><span>newEdgePathId</span><span>.</span><span>erase</span><span>(</span><span>newEdgePathId</span><span>.</span><span>begin</span><span>() </span><span>+</span><span> </span><span>iter</span><span>);</span></div></div><div><div><div>160</div></div><div><span>                </span><span>--</span><span>idx</span><span>;</span></div></div><div><div><div>161</div></div><div><span>                </span><span>--</span><span>n</span><span>;</span></div></div><div><div><div>162</div></div><div>
</div></div><div><div><div>163</div></div><div><span>                </span><span>for</span><span> (</span><span>int</span><span> </span><span>k</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>k</span><span> </span><span>&lt;</span><span> </span><span>P</span><span>; </span><span>++</span><span>k</span><span>) {</span><span>   // 该边已删除，就应对其进行封锁</span></div></div><div><div><div>164</div></div><div><span>                    </span><span>edge</span><span>[</span><span>trueEdgeId</span><span>].</span><span>Pile</span><span>[</span><span>k</span><span>] </span><span>=</span><span> </span><span>T</span><span>;</span></div></div><div><div><div>165</div></div><div><span>                    </span><span>edge</span><span>[</span><span>trueEdgeId</span><span> </span><span>+</span><span> </span><span>1</span><span>].</span><span>Pile</span><span>[</span><span>k</span><span>] </span><span>=</span><span> </span><span>T</span><span>;</span><span>   // 偶数+1</span></div></div><div><div><div>166</div></div><div><span><span>                </span></span><span>}</span></div></div><div><div><div>167</div></div><div>
</div></div><div><div><div>168</div></div><div><span>                </span><span>for</span><span> (</span><span>int</span><span> </span><span>k</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>k</span><span> </span><span>&lt;</span><span> </span><span>busCnt</span><span>; </span><span>++</span><span>k</span><span>) {</span></div></div><div><div><div>169</div></div><div>
</div></div><div><div><div>170</div></div><div><span>                    </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>nullVector</span><span>;</span></div></div><div><div><div>171</div></div><div><span>                    </span><span>buses</span><span>[</span><span>lastBusIds</span><span>[</span><span>k</span><span>]].</span><span>mutiplierId</span><span>.</span><span>swap</span><span>(</span><span>nullVector</span><span>);</span></div></div><div><div><div>172</div></div><div><span>                    </span><span>buses</span><span>[</span><span>lastBusIds</span><span>[</span><span>k</span><span>]].</span><span>curA</span><span> </span><span>=</span><span> </span><span>D</span><span>;</span></div></div><div><div><div>173</div></div><div>
</div></div><div><div><div>174</div></div><div><span>                    </span><span>addMultiplier</span><span>(</span><span>buses</span><span>[</span><span>lastBusIds</span><span>[</span><span>k</span><span>]], </span><span>lastBusIds</span><span>[</span><span>k</span><span>]);</span></div></div><div><div><div>175</div></div><div>
</div></div><div><div><div>176</div></div><div><span><span>                </span></span><span>}</span></div></div><div><div><div>177</div></div><div>
</div></div><div><div><div>178</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>179</div></div><div><span>            </span><span>else</span><span> {</span></div></div><div><div><div>180</div></div><div>
</div></div><div><div><div>181</div></div><div><span>                </span><span>for</span><span> (</span><span>int</span><span> </span><span>k</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>k</span><span> </span><span>&lt;</span><span> </span><span>stopK</span><span>; </span><span>++</span><span>k</span><span>) {</span><span>   // 把试图寻路时，造成的对网络的影响消除</span></div></div><div><div><div>182</div></div><div><span>                    </span><span>reCoverNetwork</span><span>(</span><span>lastBusIds</span><span>[</span><span>k</span><span>], </span><span>tmpLastPileIds</span><span>[</span><span>k</span><span>]);</span></div></div><div><div><div>183</div></div><div><span><span>                </span></span><span>}</span></div></div><div><div><div>184</div></div><div>
</div></div><div><div><div>185</div></div><div><span>                </span><span>for</span><span> (</span><span>int</span><span> </span><span>k</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>k</span><span> </span><span>&lt;</span><span> </span><span>busCnt</span><span>; </span><span>++</span><span>k</span><span>) {</span><span>  // 重新加载所有的边</span></div></div><div><div><div>186</div></div><div><span>                    </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>nullVector</span><span>, </span><span>nullPath1</span><span>, </span><span>nullPath2</span><span>;</span></div></div><div><div><div>187</div></div><div><span>                    </span><span>buses</span><span>[</span><span>lastBusIds</span><span>[</span><span>k</span><span>]].</span><span>mutiplierId</span><span>.</span><span>swap</span><span>(</span><span>nullVector</span><span>);</span></div></div><div><div><div>188</div></div><div><span>                    </span><span>buses</span><span>[</span><span>lastBusIds</span><span>[</span><span>k</span><span>]].</span><span>path</span><span>.</span><span>swap</span><span>(</span><span>nullPath1</span><span>);</span></div></div><div><div><div>189</div></div><div><span>                    </span><span>buses</span><span>[</span><span>lastBusIds</span><span>[</span><span>k</span><span>]].</span><span>pathTmp</span><span>.</span><span>swap</span><span>(</span><span>nullPath2</span><span>);</span></div></div><div><div><div>190</div></div><div>
</div></div><div><div><div>191</div></div><div><span>                    </span><span>buses</span><span>[</span><span>lastBusIds</span><span>[</span><span>k</span><span>]].</span><span>pileId</span><span> </span><span>=</span><span> </span><span>-</span><span>1</span><span>;</span></div></div><div><div><div>192</div></div><div><span>                    </span><span>buses</span><span>[</span><span>lastBusIds</span><span>[</span><span>k</span><span>]].</span><span>curA</span><span> </span><span>=</span><span> </span><span>D</span><span>;</span></div></div><div><div><div>193</div></div><div><span>                    </span><span>reloadBus</span><span>(</span><span>lastBusIds</span><span>[</span><span>k</span><span>], </span><span>lastPileIds</span><span>[</span><span>k</span><span>], </span><span>pathTmp</span><span>[</span><span>k</span><span>]);</span></div></div><div><div><div>194</div></div><div><span><span>                </span></span><span>}</span></div></div><div><div><div>195</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>196</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>197</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>198</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>迭代优化<a href="#迭代优化"><span>#</span></a></h3><p>迭代优化是在初赛结束之后才做出来的算法，故无法得知用上迭代优化后在初赛中可以获得怎样的成绩。但是就本地测试来看，它通过在规定的测试时间内进行多次迭代，可以搭配计时完美利用分配完成后剩余的大量时间对网络进行调整优化，可以大幅度降低成本。</p><p>迭代优化的过程其实类似于删边，先把需要迭代的业务保存下来，然后进行重新分配，将重新分配的结果与原本的分配结果比较看看有无进步，若有进步则保留，无进步则还原之前的状态。这样持续迭代多次，进步就能累积下去得到更好的结果。</p><p>迭代优化的方案有很多，我们做过四个方案，分别是 <code>reAllocateBus1</code>—<code>reAllocateBus4</code>，四个方案的区别主要在于评判重新分配的结果的标准或过程中的约束。四个方案都是先随机出一个 <code>gap</code>，然后从业务中一次随机抽取 <code>gap</code> 个业务作为一个单位去考察重新分配后有无更好，这个抽取过程在一次迭代中会重复多次，具体视总体业务量来确定，抽取次数过多会影响效率进而减少迭代次数使效果变差。</p><p><code>reAllocateBus1</code> 对重新分配结果的评判标准为总的边数是否减少，若总边数减少则认为成功，采用重新分配的结果。其在进行重新分配寻路的时候允许进行加边操作，以求获得较好的路径。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>void</span><span> </span><span>reAllocateBus1</span><span>(</span><span>int</span><span><span> </span><span>HLim</span><span>) {</span></span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>    </span><span>int</span><span> </span><span>gap</span><span> </span><span>=</span><span> </span><span>max</span><span>(</span><span>int</span><span>(</span><span>0.025</span><span> </span><span>*</span><span> </span><span>T</span><span>), </span><span>20</span><span>);</span></div></div><div><div><div>4</div></div><div><span>    </span><span>if</span><span> (</span><span>gap</span><span> </span><span>&gt;</span><span> </span><span>T</span><span>)</span></div></div><div><div><div>5</div></div><div><span>        </span><span>return</span><span>;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>    </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>busIdx</span><span>(</span><span>gap</span><span>, </span><span>0</span><span>);</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>i</span><span> </span><span>+</span><span> </span><span>gap</span><span> </span><span>&lt;</span><span> </span><span>HLim</span><span>; </span><span>i</span><span> </span><span>=</span><span> </span><span>i</span><span> </span><span>+</span><span> </span><span>gap</span><span>) {</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>        </span><span>srand</span><span>(</span><span>42</span><span>);</span><span>  // 设置随机数种子</span></div></div><div><div><div>12</div></div><div><span>        </span><span>random_shuffle</span><span>(</span><span>totBusIdx</span><span>.</span><span>begin</span><span>(), </span><span>totBusIdx</span><span>.</span><span>end</span><span>());</span></div></div><div><div><div>13</div></div><div><span>        </span><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>i</span><span> </span><span>&lt;</span><span> </span><span>gap</span><span>; </span><span>++</span><span>i</span><span>) {</span></div></div><div><div><div>14</div></div><div><span>            </span><span>busIdx</span><span>[</span><span>i</span><span>] </span><span>=</span><span> </span><span>totBusIdx</span><span>[</span><span>i</span><span>];</span></div></div><div><div><div>15</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span>        </span><span>int</span><span> </span><span>oriEdgeNum</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>        </span><span>vector</span><span>&lt;</span><span>vector</span><span>&lt;</span><span>int</span><span>&gt;&gt; </span><span>pathTmp1</span><span>(</span><span>gap</span><span>, </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt;());</span><span>     // 用于此后重新加载边</span></div></div><div><div><div>20</div></div><div><span>        </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>pileTmp1</span><span>(</span><span>gap</span><span>, </span><span>-</span><span>1</span><span>);</span></div></div><div><div><div>21</div></div><div><span>        </span><span>for</span><span> (</span><span>int</span><span> </span><span>j</span><span> </span><span>=</span><span> </span><span>i</span><span>, </span><span>busId</span><span>; </span><span>j</span><span> </span><span>&lt;</span><span> </span><span>i</span><span> </span><span>+</span><span> </span><span>gap</span><span>; </span><span>++</span><span>j</span><span>) {</span></div></div><div><div><div>22</div></div><div><span>            </span><span>busId</span><span> </span><span>=</span><span> </span><span>busIdx</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>];</span></div></div><div><div><div>23</div></div><div><span>            </span><span>oriEdgeNum</span><span> </span><span>+=</span><span> </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>path</span><span>.</span><span>size</span><span>();</span></div></div><div><div><div>24</div></div><div><span>            </span><span>pathTmp1</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>] </span><span>=</span><span> </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>pathTmp</span><span>;</span></div></div><div><div><div>25</div></div><div><span>            </span><span>pileTmp1</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>] </span><span>=</span><span> </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>pileId</span><span>;</span></div></div><div><div><div>26</div></div><div><span>            </span><span>reCoverNetwork</span><span>(</span><span>busId</span><span>, </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>pileId</span><span>);</span></div></div><div><div><div>27</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>28</div></div><div>
</div></div><div><div><div>29</div></div><div><span>        </span><span>int</span><span> </span><span>curEdgeNum</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>30</div></div><div><span>        </span><span>bool</span><span> </span><span>findPath</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>31</div></div><div><span>        </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>pileTmp2</span><span>(</span><span>gap</span><span>, </span><span>-</span><span>1</span><span>);</span></div></div><div><div><div>32</div></div><div><span>        </span><span>for</span><span> (</span><span>int</span><span> </span><span>j</span><span> </span><span>=</span><span> </span><span>i</span><span> </span><span>+</span><span> </span><span>gap</span><span> </span><span>-</span><span> </span><span>1</span><span>, </span><span>busId</span><span>; </span><span>j</span><span> </span><span>&gt;=</span><span> </span><span>i</span><span>; </span><span>--</span><span>j</span><span>) {</span></div></div><div><div><div>33</div></div><div><span>            </span><span>busId</span><span> </span><span>=</span><span> </span><span>busIdx</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>];</span></div></div><div><div><div>34</div></div><div><span>            </span><span>loadBus</span><span>(</span><span>busId</span><span>, </span><span>false</span><span>);</span></div></div><div><div><div>35</div></div><div><span>            </span><span>pileTmp2</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>] </span><span>=</span><span> </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>pileId</span><span>;</span></div></div><div><div><div>36</div></div><div><span>            </span><span>curEdgeNum</span><span> </span><span>+=</span><span> </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>path</span><span>.</span><span>size</span><span>();</span></div></div><div><div><div>37</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>38</div></div><div>
</div></div><div><div><div>39</div></div><div><span>        </span><span>if</span><span> (</span><span>1.05</span><span> </span><span>*</span><span> </span><span>curEdgeNum</span><span> </span><span>&lt;</span><span> </span><span>oriEdgeNum</span><span>) {</span><span>  // 总体的边数减少，接受迁移</span></div></div><div><div><div>40</div></div><div><span>            </span><span>continue</span><span>;</span></div></div><div><div><div>41</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>42</div></div><div><span>        </span><span>else</span><span> {</span><span>  // 否则，回复原状态</span></div></div><div><div><div>43</div></div><div><span>            </span><span>for</span><span> (</span><span>int</span><span> </span><span>j</span><span> </span><span>=</span><span> </span><span>i</span><span> </span><span>+</span><span> </span><span>gap</span><span> </span><span>-</span><span> </span><span>1</span><span>, </span><span>busId</span><span>; </span><span>j</span><span> </span><span>&gt;=</span><span> </span><span>i</span><span>; </span><span>--</span><span>j</span><span>) {</span><span>   // 把试图寻路时，造成的对网络的影响消除</span></div></div><div><div><div>44</div></div><div><span>                </span><span>busId</span><span> </span><span>=</span><span> </span><span>busIdx</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>];</span></div></div><div><div><div>45</div></div><div><span>                </span><span>reCoverNetwork</span><span>(</span><span>busId</span><span>, </span><span>pileTmp2</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>]);</span></div></div><div><div><div>46</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>47</div></div><div>
</div></div><div><div><div>48</div></div><div><span>            </span><span>for</span><span> (</span><span>int</span><span> </span><span>j</span><span> </span><span>=</span><span> </span><span>i</span><span>, </span><span>busId</span><span>; </span><span>j</span><span> </span><span>&lt;</span><span> </span><span>i</span><span> </span><span>+</span><span> </span><span>gap</span><span>; </span><span>++</span><span>j</span><span>) {</span><span>  // 重新加载所有的边</span></div></div><div><div><div>49</div></div><div><span>                </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>nullVector</span><span>, </span><span>nullPath1</span><span>, </span><span>nullPath2</span><span>;</span></div></div><div><div><div>50</div></div><div><span>                </span><span>busId</span><span> </span><span>=</span><span> </span><span>busIdx</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>];</span></div></div><div><div><div>51</div></div><div><span>                </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>mutiplierId</span><span>.</span><span>swap</span><span>(</span><span>nullVector</span><span>);</span></div></div><div><div><div>52</div></div><div><span>                </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>path</span><span>.</span><span>swap</span><span>(</span><span>nullPath1</span><span>);</span></div></div><div><div><div>53</div></div><div><span>                </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>pathTmp</span><span>.</span><span>swap</span><span>(</span><span>nullPath2</span><span>);</span></div></div><div><div><div>54</div></div><div>
</div></div><div><div><div>55</div></div><div><span>                </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>pileId</span><span> </span><span>=</span><span> </span><span>-</span><span>1</span><span>;</span></div></div><div><div><div>56</div></div><div><span>                </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>curA</span><span> </span><span>=</span><span> </span><span>D</span><span>;</span></div></div><div><div><div>57</div></div><div><span>                </span><span>reloadBus</span><span>(</span><span>busId</span><span>, </span><span>pileTmp1</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>], </span><span>pathTmp1</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>]);</span></div></div><div><div><div>58</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>59</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>60</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>61</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><code>reAllocateBus2</code> 对重新分配结果的评判标准也是总路径边数是否减少，与 <code>reAllocateBus1</code> 的区别在于在重新分配寻路的过程中不允许加边操作，避免迭代过程继续加边，试图减小加边数。但经过实测效果并不好，依然存在全局性能不好的问题。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>void</span><span> </span><span>reAllocateBus2</span><span>(</span><span>int</span><span><span> </span><span>HLim</span><span>) {</span></span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>    </span><span>int</span><span> </span><span>gap</span><span> </span><span>=</span><span> </span><span>max</span><span>(</span><span>int</span><span>(</span><span>0.05</span><span> </span><span>*</span><span> </span><span>T</span><span>), </span><span>20</span><span>);</span></div></div><div><div><div>4</div></div><div><span>    </span><span>if</span><span> (</span><span>gap</span><span> </span><span>&gt;</span><span> </span><span>T</span><span>)</span></div></div><div><div><div>5</div></div><div><span>        </span><span>return</span><span>;</span></div></div><div><div><div>6</div></div><div><span>    </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>totBusIdx</span><span>(</span><span>T</span><span>, </span><span>0</span><span>);</span></div></div><div><div><div>7</div></div><div><span>    </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>busIdx</span><span>(</span><span>gap</span><span>, </span><span>0</span><span>);</span></div></div><div><div><div>8</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>i</span><span> </span><span>&lt;</span><span> </span><span>T</span><span>; </span><span>++</span><span>i</span><span>)</span></div></div><div><div><div>9</div></div><div><span>        </span><span>totBusIdx</span><span>[</span><span>i</span><span>] </span><span>=</span><span> </span><span>i</span><span>;</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>i</span><span> </span><span>+</span><span> </span><span>gap</span><span> </span><span>&lt;</span><span> </span><span>HLim</span><span>; </span><span>i</span><span> </span><span>=</span><span> </span><span>i</span><span> </span><span>+</span><span> </span><span>gap</span><span>) {</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>        </span><span>srand</span><span>(</span><span>time</span><span>(</span><span>NULL</span><span>));</span><span>  // 设置随机数种子</span></div></div><div><div><div>14</div></div><div><span>        </span><span>random_shuffle</span><span>(</span><span>totBusIdx</span><span>.</span><span>begin</span><span>(), </span><span>totBusIdx</span><span>.</span><span>end</span><span>());</span></div></div><div><div><div>15</div></div><div><span>        </span><span>for</span><span> (</span><span>int</span><span> </span><span>k</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>k</span><span> </span><span>&lt;</span><span> </span><span>gap</span><span>; </span><span>++</span><span>k</span><span>) {</span></div></div><div><div><div>16</div></div><div><span>            </span><span>busIdx</span><span>[</span><span>k</span><span>] </span><span>=</span><span> </span><span>totBusIdx</span><span>[</span><span>k</span><span>];</span></div></div><div><div><div>17</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>        </span><span>int</span><span> </span><span>oriEdgeNum</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>        </span><span>vector</span><span>&lt;</span><span>vector</span><span>&lt;</span><span>int</span><span>&gt;&gt; </span><span>pathTmp1</span><span>(</span><span>gap</span><span>, </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt;());</span><span>     // 用于此后重新加载边</span></div></div><div><div><div>22</div></div><div><span>        </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>pileTmp1</span><span>(</span><span>gap</span><span>, </span><span>-</span><span>1</span><span>);</span></div></div><div><div><div>23</div></div><div><span>        </span><span>for</span><span> (</span><span>int</span><span> </span><span>j</span><span> </span><span>=</span><span> </span><span>i</span><span>, </span><span>busId</span><span>; </span><span>j</span><span> </span><span>&lt;</span><span> </span><span>i</span><span> </span><span>+</span><span> </span><span>gap</span><span>; </span><span>++</span><span>j</span><span>) {</span></div></div><div><div><div>24</div></div><div><span>            </span><span>busId</span><span> </span><span>=</span><span> </span><span>busIdx</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>];</span></div></div><div><div><div>25</div></div><div><span>            </span><span>oriEdgeNum</span><span> </span><span>+=</span><span> </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>path</span><span>.</span><span>size</span><span>();</span></div></div><div><div><div>26</div></div><div><span>            </span><span>pathTmp1</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>] </span><span>=</span><span> </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>pathTmp</span><span>;</span></div></div><div><div><div>27</div></div><div><span>            </span><span>pileTmp1</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>] </span><span>=</span><span> </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>pileId</span><span>;</span></div></div><div><div><div>28</div></div><div><span>            </span><span>reCoverNetwork</span><span>(</span><span>busId</span><span>, </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>pileId</span><span>);</span></div></div><div><div><div>29</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>30</div></div><div>
</div></div><div><div><div>31</div></div><div><span>        </span><span>int</span><span> </span><span>curEdgeNum</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>32</div></div><div><span>        </span><span>bool</span><span> </span><span>findPath</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>33</div></div><div><span>        </span><span>vector</span><span>&lt;</span><span>vector</span><span>&lt;</span><span>int</span><span>&gt;&gt; </span><span>pathTmp2</span><span>(</span><span>gap</span><span>, </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt;());</span><span>     // 用于此后重新加载边</span></div></div><div><div><div>34</div></div><div><span>        </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>pileTmp2</span><span>(</span><span>gap</span><span>, </span><span>-</span><span>1</span><span>);</span></div></div><div><div><div>35</div></div><div>
</div></div><div><div><div>36</div></div><div><span>        </span><span>for</span><span> (</span><span>int</span><span> </span><span>j</span><span> </span><span>=</span><span> </span><span>i</span><span> </span><span>+</span><span> </span><span>gap</span><span> </span><span>-</span><span> </span><span>1</span><span>, </span><span>busId</span><span>; </span><span>j</span><span> </span><span>&gt;=</span><span> </span><span>i</span><span>; </span><span>--</span><span>j</span><span>) {</span></div></div><div><div><div>37</div></div><div>
</div></div><div><div><div>38</div></div><div><span>            </span><span>busId</span><span> </span><span>=</span><span> </span><span>busIdx</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>];</span></div></div><div><div><div>39</div></div><div><span>            </span><span>findPath</span><span> </span><span>=</span><span> </span><span>BFS5</span><span>(</span><span>buses</span><span>[</span><span>busId</span><span>], </span><span>-</span><span>1</span><span>);</span></div></div><div><div><div>40</div></div><div><span>            </span><span>if</span><span> (</span><span>findPath</span><span>) {</span></div></div><div><div><div>41</div></div><div><span>                </span><span>pathTmp2</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>] </span><span>=</span><span> </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>pathTmp</span><span>;</span></div></div><div><div><div>42</div></div><div><span>                </span><span>pileTmp2</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>] </span><span>=</span><span> </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>pileId</span><span>;</span></div></div><div><div><div>43</div></div><div><span>                </span><span>curEdgeNum</span><span> </span><span>+=</span><span> </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>path</span><span>.</span><span>size</span><span>();</span></div></div><div><div><div>44</div></div><div>
</div></div><div><div><div>45</div></div><div><span>                </span><span>int</span><span> </span><span>curNode</span><span> </span><span>=</span><span> </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>start</span><span>, </span><span>trueNextEdgeId</span><span>;</span></div></div><div><div><div>46</div></div><div><span>                </span><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>i</span><span> </span><span>&lt;</span><span> </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>path</span><span>.</span><span>size</span><span>(); </span><span>++</span><span>i</span><span>) {</span></div></div><div><div><div>47</div></div><div>
</div></div><div><div><div>48</div></div><div><span>                    </span><span>if</span><span> (</span><span>edge</span><span>[</span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>path</span><span>[</span><span>i</span><span>] </span><span>*</span><span> </span><span>2</span><span>].</span><span>from</span><span> </span><span>==</span><span> </span><span>curNode</span><span>)</span></div></div><div><div><div>49</div></div><div><span>                        </span><span>trueNextEdgeId</span><span> </span><span>=</span><span> </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>path</span><span>[</span><span>i</span><span>] </span><span>*</span><span> </span><span>2</span><span>;</span></div></div><div><div><div>50</div></div><div><span>                    </span><span>else</span></div></div><div><div><div>51</div></div><div><span>                        </span><span>trueNextEdgeId</span><span> </span><span>=</span><span> </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>path</span><span>[</span><span>i</span><span>] </span><span>*</span><span> </span><span>2</span><span> </span><span>+</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>52</div></div><div><span>                    </span><span>curNode</span><span> </span><span>=</span><span> </span><span>edge</span><span>[</span><span>trueNextEdgeId</span><span>].</span><span>to</span><span>;</span></div></div><div><div><div>53</div></div><div>
</div></div><div><div><div>54</div></div><div><span>                    </span><span>if</span><span> (</span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>curA</span><span> </span><span>&gt;=</span><span> </span><span>edge</span><span>[</span><span>trueNextEdgeId</span><span>].</span><span>trueD</span><span>) {</span></div></div><div><div><div>55</div></div><div><span>                        </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>curA</span><span> </span><span>-=</span><span> </span><span>edge</span><span>[</span><span>trueNextEdgeId</span><span>].</span><span>trueD</span><span>;</span></div></div><div><div><div>56</div></div><div><span><span>                    </span></span><span>}</span></div></div><div><div><div>57</div></div><div><span>                    </span><span>else</span><span> {</span></div></div><div><div><div>58</div></div><div><span>                        </span><span>node</span><span>[</span><span>edge</span><span>[</span><span>trueNextEdgeId</span><span>].</span><span>from</span><span>].</span><span>Multiplier</span><span>[</span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>pileId</span><span>] </span><span>=</span><span> </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>pileId</span><span>;</span></div></div><div><div><div>59</div></div><div><span>                        </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>curA</span><span> </span><span>=</span><span> </span><span>D</span><span>;</span></div></div><div><div><div>60</div></div><div><span>                        </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>curA</span><span> </span><span>-=</span><span> </span><span>edge</span><span>[</span><span>trueNextEdgeId</span><span>].</span><span>trueD</span><span>;</span></div></div><div><div><div>61</div></div><div><span>                        </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>mutiplierId</span><span>.</span><span>push_back</span><span>(</span><span>edge</span><span>[</span><span>trueNextEdgeId</span><span>].</span><span>from</span><span>);</span></div></div><div><div><div>62</div></div><div><span><span>                    </span></span><span>}</span></div></div><div><div><div>63</div></div><div><span><span>                </span></span><span>}</span></div></div><div><div><div>64</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>65</div></div><div><span>            </span><span>else</span><span> {</span><span>  // BFS5找不到路时，不会对网络和业务产生任何影响</span></div></div><div><div><div>66</div></div><div><span>                </span><span>findPath</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>67</div></div><div><span>                </span><span>break</span><span>;</span></div></div><div><div><div>68</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>69</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>70</div></div><div>
</div></div><div><div><div>71</div></div><div><span>        </span><span>if</span><span> (</span><span>findPath</span><span> </span><span>&amp;&amp;</span><span> </span><span>1.025</span><span> </span><span>*</span><span> </span><span>curEdgeNum</span><span> </span><span>&lt;</span><span> </span><span>oriEdgeNum</span><span>) {</span><span>  // 总体的边数减少，接受迁移</span></div></div><div><div><div>72</div></div><div><span>            </span><span>continue</span><span>;</span></div></div><div><div><div>73</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>74</div></div><div><span>        </span><span>else</span><span> {</span><span>  // 否则，回复原状态</span></div></div><div><div><div>75</div></div><div><span>            </span><span>for</span><span> (</span><span>int</span><span> </span><span>j</span><span> </span><span>=</span><span> </span><span>i</span><span> </span><span>+</span><span> </span><span>gap</span><span> </span><span>-</span><span> </span><span>1</span><span>, </span><span>busId</span><span>; </span><span>j</span><span> </span><span>&gt;=</span><span> </span><span>i</span><span>; </span><span>--</span><span>j</span><span>) {</span><span>   // 把试图寻路时，造成的对网络的影响消除</span></div></div><div><div><div>76</div></div><div><span>                </span><span>if</span><span> (</span><span>pathTmp2</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>].</span><span>size</span><span>() </span><span>==</span><span> </span><span>0</span><span>)</span><span>        // 该业务寻路失败，对网络不造成影响</span></div></div><div><div><div>77</div></div><div><span>                    </span><span>continue</span><span>;</span></div></div><div><div><div>78</div></div><div><span>                </span><span>busId</span><span> </span><span>=</span><span> </span><span>busIdx</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>];</span></div></div><div><div><div>79</div></div><div><span>                </span><span>reCoverNetwork</span><span>(</span><span>busId</span><span>, </span><span>pileTmp2</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>]);</span></div></div><div><div><div>80</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>81</div></div><div>
</div></div><div><div><div>82</div></div><div><span>            </span><span>for</span><span> (</span><span>int</span><span> </span><span>j</span><span> </span><span>=</span><span> </span><span>i</span><span>, </span><span>busId</span><span>; </span><span>j</span><span> </span><span>&lt;</span><span> </span><span>i</span><span> </span><span>+</span><span> </span><span>gap</span><span>; </span><span>++</span><span>j</span><span>) {</span><span>  // 重新加载所有的边</span></div></div><div><div><div>83</div></div><div>
</div></div><div><div><div>84</div></div><div><span>                </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>nullVector</span><span>, </span><span>nullPath1</span><span>, </span><span>nullPath2</span><span>;</span></div></div><div><div><div>85</div></div><div><span>                </span><span>busId</span><span> </span><span>=</span><span> </span><span>busIdx</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>];</span></div></div><div><div><div>86</div></div><div><span>                </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>mutiplierId</span><span>.</span><span>swap</span><span>(</span><span>nullVector</span><span>);</span></div></div><div><div><div>87</div></div><div><span>                </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>path</span><span>.</span><span>swap</span><span>(</span><span>nullPath1</span><span>);</span></div></div><div><div><div>88</div></div><div><span>                </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>pathTmp</span><span>.</span><span>swap</span><span>(</span><span>nullPath2</span><span>);</span></div></div><div><div><div>89</div></div><div>
</div></div><div><div><div>90</div></div><div><span>                </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>pileId</span><span> </span><span>=</span><span> </span><span>-</span><span>1</span><span>;</span></div></div><div><div><div>91</div></div><div><span>                </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>curA</span><span> </span><span>=</span><span> </span><span>D</span><span>;</span></div></div><div><div><div>92</div></div><div><span>                </span><span>reloadBus</span><span>(</span><span>busId</span><span>, </span><span>pileTmp1</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>], </span><span>pathTmp1</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>]);</span></div></div><div><div><div>93</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>94</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>95</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>96</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><code>reAllocateBus3</code> 对重新分配结果的评判标准也是总路径边数是否减少，但是在挑选迭代业务时有所不同。它先考察每一个业务所经过的路径长度是否小于 <code>最短路径长度*goofBadGap</code>，以此分离出“分配良好”和“分配不良好”的业务。然后它以某一概率抽取“不良好”的业务，剩余则从“良好”中抽取，以此尽可能试图抽出较多“不良好”的业务进行重新分配。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>void</span><span> </span><span>reAllocateBus3</span><span>(</span><span>int</span><span><span> </span><span>HLim</span><span>) {</span></span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>    </span><span>int</span><span> </span><span>gap</span><span> </span><span>=</span><span> </span><span>max</span><span>(</span><span>int</span><span>(</span><span>0.025</span><span> </span><span>*</span><span> </span><span>T</span><span>), </span><span>20</span><span>);</span></div></div><div><div><div>4</div></div><div><span>    </span><span>if</span><span> (</span><span>gap</span><span> </span><span>&gt;</span><span> </span><span>T</span><span>)</span></div></div><div><div><div>5</div></div><div><span>        </span><span>return</span><span>;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>    </span><span>double</span><span> </span><span>ratio</span><span> </span><span>=</span><span> </span><span>0.5</span><span>;</span><span>     // 以ratio的概率，选择不良好的业务进行分配</span></div></div><div><div><div>8</div></div><div><span>    </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>goodBusId</span><span>;</span><span>  // 良好分配的业务，“良好”的定义是该业务所经过的路径长度小于最短路径长度*goofBadGap</span></div></div><div><div><div>9</div></div><div><span>    </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>badBusId</span><span>;</span><span>   // 不良好分配的业务</span></div></div><div><div><div>10</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>i</span><span> </span><span>&lt;</span><span> </span><span>T</span><span>; </span><span>++</span><span>i</span><span>)</span></div></div><div><div><div>11</div></div><div><span>        </span><span>if</span><span> (</span><span>buses</span><span>[</span><span>i</span><span>].</span><span>isBusWellAllocate</span><span>)</span></div></div><div><div><div>12</div></div><div><span>            </span><span>goodBusId</span><span>.</span><span>push_back</span><span>(</span><span>i</span><span>);</span></div></div><div><div><div>13</div></div><div><span>        </span><span>else</span></div></div><div><div><div>14</div></div><div><span>            </span><span>badBusId</span><span>.</span><span>push_back</span><span>(</span><span>i</span><span>);</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>    </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>busIdx</span><span>(</span><span>gap</span><span>, </span><span>0</span><span>);</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>i</span><span> </span><span>+</span><span> </span><span>gap</span><span> </span><span>&lt;</span><span> </span><span>HLim</span><span>; </span><span>i</span><span> </span><span>=</span><span> </span><span>i</span><span> </span><span>+</span><span> </span><span>gap</span><span>) {</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>        </span><span>srand</span><span>(</span><span>time</span><span>(</span><span>NULL</span><span>) </span><span>+</span><span> </span><span>rand</span><span>() </span><span>%</span><span> </span><span>1000</span><span>);</span><span>  // 设置随机数种子</span></div></div><div><div><div>21</div></div><div><span>        </span><span>random_shuffle</span><span>(</span><span>goodBusId</span><span>.</span><span>begin</span><span>(), </span><span>goodBusId</span><span>.</span><span>end</span><span>());</span></div></div><div><div><div>22</div></div><div><span>        </span><span>random_shuffle</span><span>(</span><span>badBusId</span><span>.</span><span>begin</span><span>(), </span><span>badBusId</span><span>.</span><span>end</span><span>());</span></div></div><div><div><div>23</div></div><div><span>        </span><span>int</span><span> </span><span>goodBusSize</span><span> </span><span>=</span><span> </span><span>goodBusId</span><span>.</span><span>size</span><span>(), </span><span>badBusSize</span><span> </span><span>=</span><span> </span><span>badBusId</span><span>.</span><span>size</span><span>();</span></div></div><div><div><div>24</div></div><div>
</div></div><div><div><div>25</div></div><div><span>        </span><span>for</span><span> (</span><span>int</span><span> </span><span>j</span><span> </span><span>=</span><span> </span><span>0</span><span>, </span><span>m</span><span> </span><span>=</span><span> </span><span>0</span><span>, </span><span>n</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>j</span><span> </span><span>&lt;</span><span> </span><span>gap</span><span>; </span><span>++</span><span>j</span><span>) {</span></div></div><div><div><div>26</div></div><div>
</div></div><div><div><div>27</div></div><div><span>            </span><span>if</span><span> (</span><span>n</span><span> </span><span>&gt;=</span><span> </span><span>goodBusSize</span><span>) {</span></div></div><div><div><div>28</div></div><div><span>                </span><span>busIdx</span><span>[</span><span>j</span><span>] </span><span>=</span><span> </span><span>badBusId</span><span>[</span><span>m</span><span>++</span><span>];</span></div></div><div><div><div>29</div></div><div><span>                </span><span>continue</span><span>;</span></div></div><div><div><div>30</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>31</div></div><div><span>            </span><span>if</span><span> (</span><span>m</span><span> </span><span>&gt;=</span><span> </span><span>badBusSize</span><span>) {</span></div></div><div><div><div>32</div></div><div><span>                </span><span>busIdx</span><span>[</span><span>j</span><span>] </span><span>=</span><span> </span><span>goodBusId</span><span>[</span><span>n</span><span>++</span><span>];</span></div></div><div><div><div>33</div></div><div><span>                </span><span>continue</span><span>;</span></div></div><div><div><div>34</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>35</div></div><div><span>            </span><span>double</span><span> </span><span>curRatio</span><span> </span><span>=</span><span> (</span><span>double</span><span>)(</span><span>rand</span><span>()) </span><span>/</span><span> </span><span>RAND_MAX</span><span>;</span></div></div><div><div><div>36</div></div><div><span>            </span><span>if</span><span> (</span><span>curRatio</span><span> </span><span>&lt;</span><span> </span><span>ratio</span><span>)</span><span>   // 以ratio的概率，选择不良好的业务进行分配</span></div></div><div><div><div>37</div></div><div><span>                </span><span>busIdx</span><span>[</span><span>j</span><span>] </span><span>=</span><span> </span><span>badBusId</span><span>[</span><span>m</span><span>++</span><span>];</span></div></div><div><div><div>38</div></div><div><span>            </span><span>else</span></div></div><div><div><div>39</div></div><div><span>                </span><span>busIdx</span><span>[</span><span>j</span><span>] </span><span>=</span><span> </span><span>goodBusId</span><span>[</span><span>n</span><span>++</span><span>];</span></div></div><div><div><div>40</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>41</div></div><div>
</div></div><div><div><div>42</div></div><div><span>        </span><span>int</span><span> </span><span>oriEdgeNum</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>43</div></div><div><span>        </span><span>vector</span><span>&lt;</span><span>vector</span><span>&lt;</span><span>int</span><span>&gt;&gt; </span><span>pathTmp1</span><span>(</span><span>gap</span><span>, </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt;());</span><span>     // 用于此后重新加载边</span></div></div><div><div><div>44</div></div><div><span>        </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>pileTmp1</span><span>(</span><span>gap</span><span>, </span><span>-</span><span>1</span><span>);</span></div></div><div><div><div>45</div></div><div><span>        </span><span>for</span><span> (</span><span>int</span><span> </span><span>j</span><span> </span><span>=</span><span> </span><span>i</span><span>, </span><span>busId</span><span>; </span><span>j</span><span> </span><span>&lt;</span><span> </span><span>i</span><span> </span><span>+</span><span> </span><span>gap</span><span>; </span><span>++</span><span>j</span><span>) {</span></div></div><div><div><div>46</div></div><div><span>            </span><span>busId</span><span> </span><span>=</span><span> </span><span>busIdx</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>];</span></div></div><div><div><div>47</div></div><div><span>            </span><span>oriEdgeNum</span><span> </span><span>+=</span><span> </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>path</span><span>.</span><span>size</span><span>();</span></div></div><div><div><div>48</div></div><div><span>            </span><span>pathTmp1</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>] </span><span>=</span><span> </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>pathTmp</span><span>;</span></div></div><div><div><div>49</div></div><div><span>            </span><span>pileTmp1</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>] </span><span>=</span><span> </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>pileId</span><span>;</span></div></div><div><div><div>50</div></div><div><span>            </span><span>reCoverNetwork</span><span>(</span><span>busId</span><span>, </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>pileId</span><span>);</span></div></div><div><div><div>51</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>52</div></div><div>
</div></div><div><div><div>53</div></div><div><span>        </span><span>int</span><span> </span><span>oriCntEdge</span><span> </span><span>=</span><span> </span><span>cntEdge</span><span>;</span></div></div><div><div><div>54</div></div><div><span>        </span><span>int</span><span> </span><span>curEdgeNum</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>55</div></div><div><span>        </span><span>bool</span><span> </span><span>findPath</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>56</div></div><div><span>        </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>pileTmp2</span><span>(</span><span>gap</span><span>, </span><span>-</span><span>1</span><span>);</span></div></div><div><div><div>57</div></div><div><span>        </span><span>for</span><span> (</span><span>int</span><span> </span><span>j</span><span> </span><span>=</span><span> </span><span>i</span><span> </span><span>+</span><span> </span><span>gap</span><span> </span><span>-</span><span> </span><span>1</span><span>, </span><span>busId</span><span>; </span><span>j</span><span> </span><span>&gt;=</span><span> </span><span>i</span><span>; </span><span>--</span><span>j</span><span>) {</span></div></div><div><div><div>58</div></div><div><span>            </span><span>busId</span><span> </span><span>=</span><span> </span><span>busIdx</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>];</span></div></div><div><div><div>59</div></div><div><span>            </span><span>loadBus</span><span>(</span><span>busId</span><span>, </span><span>false</span><span>);</span></div></div><div><div><div>60</div></div><div><span>            </span><span>pileTmp2</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>] </span><span>=</span><span> </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>pileId</span><span>;</span></div></div><div><div><div>61</div></div><div><span>            </span><span>curEdgeNum</span><span> </span><span>+=</span><span> </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>path</span><span>.</span><span>size</span><span>();</span></div></div><div><div><div>62</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>63</div></div><div>
</div></div><div><div><div>64</div></div><div><span>        </span><span>if</span><span> (</span><span>1.05</span><span> </span><span>*</span><span> </span><span>curEdgeNum</span><span> </span><span>&lt;</span><span> </span><span>oriEdgeNum</span><span>) {</span><span>  // 总体的边数减少，接受迁移</span></div></div><div><div><div>65</div></div><div><span>            </span><span>continue</span><span>;</span></div></div><div><div><div>66</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>67</div></div><div><span>        </span><span>else</span><span> {</span><span>  // 否则，回复原状态</span></div></div><div><div><div>68</div></div><div><span>            </span><span>for</span><span> (</span><span>int</span><span> </span><span>j</span><span> </span><span>=</span><span> </span><span>i</span><span> </span><span>+</span><span> </span><span>gap</span><span> </span><span>-</span><span> </span><span>1</span><span>, </span><span>busId</span><span>; </span><span>j</span><span> </span><span>&gt;=</span><span> </span><span>i</span><span>; </span><span>--</span><span>j</span><span>) {</span><span>   // 把试图寻路时，造成的对网络的影响消除</span></div></div><div><div><div>69</div></div><div><span>                </span><span>busId</span><span> </span><span>=</span><span> </span><span>busIdx</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>];</span></div></div><div><div><div>70</div></div><div><span>                </span><span>reCoverNetwork</span><span>(</span><span>busId</span><span>, </span><span>pileTmp2</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>]);</span></div></div><div><div><div>71</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>72</div></div><div>
</div></div><div><div><div>73</div></div><div><span>            </span><span>for</span><span> (</span><span>int</span><span> </span><span>j</span><span> </span><span>=</span><span> </span><span>i</span><span>, </span><span>busId</span><span>; </span><span>j</span><span> </span><span>&lt;</span><span> </span><span>i</span><span> </span><span>+</span><span> </span><span>gap</span><span>; </span><span>++</span><span>j</span><span>) {</span><span>  // 重新加载所有的边</span></div></div><div><div><div>74</div></div><div><span>                </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>nullVector</span><span>, </span><span>nullPath1</span><span>, </span><span>nullPath2</span><span>;</span></div></div><div><div><div>75</div></div><div><span>                </span><span>busId</span><span> </span><span>=</span><span> </span><span>busIdx</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>];</span></div></div><div><div><div>76</div></div><div><span>                </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>mutiplierId</span><span>.</span><span>swap</span><span>(</span><span>nullVector</span><span>);</span></div></div><div><div><div>77</div></div><div><span>                </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>path</span><span>.</span><span>swap</span><span>(</span><span>nullPath1</span><span>);</span></div></div><div><div><div>78</div></div><div><span>                </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>pathTmp</span><span>.</span><span>swap</span><span>(</span><span>nullPath2</span><span>);</span></div></div><div><div><div>79</div></div><div>
</div></div><div><div><div>80</div></div><div><span>                </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>pileId</span><span> </span><span>=</span><span> </span><span>-</span><span>1</span><span>;</span></div></div><div><div><div>81</div></div><div><span>                </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>curA</span><span> </span><span>=</span><span> </span><span>D</span><span>;</span></div></div><div><div><div>82</div></div><div><span>                </span><span>reloadBus</span><span>(</span><span>busId</span><span>, </span><span>pileTmp1</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>], </span><span>pathTmp1</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>]);</span></div></div><div><div><div>83</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>84</div></div><div>
</div></div><div><div><div>85</div></div><div><span><span>            </span></span><span>// 在这里利用cntEdge的变化来及时删除无用新边</span></div></div><div><div><div>86</div></div><div><span><span>            </span></span><span>//for (int j = oriCntEdge; j &lt; cntEdge; j = j + 2) {</span></div></div><div><div><div>87</div></div><div>
</div></div><div><div><div>88</div></div><div><span><span>            </span></span><span>//    int iter = find(newEdgePathId.begin(), newEdgePathId.end(), j / 2) - newEdgePathId.begin();</span></div></div><div><div><div>89</div></div><div><span><span>            </span></span><span>//    newEdge.erase(newEdge.begin() + iter);</span></div></div><div><div><div>90</div></div><div><span><span>            </span></span><span>//    newEdgePathId.erase(newEdgePathId.begin() + iter);</span></div></div><div><div><div>91</div></div><div>
</div></div><div><div><div>92</div></div><div><span><span>            </span></span><span>//    for (int k = 0; k &lt; P; ++k) {   // 该边已删除，就应对其进行封锁</span></div></div><div><div><div>93</div></div><div><span><span>            </span></span><span>//        edge[j].Pile[k] = T;</span></div></div><div><div><div>94</div></div><div><span><span>            </span></span><span>//        edge[j + 1].Pile[k] = T;   // 偶数+1</span></div></div><div><div><div>95</div></div><div><span><span>            </span></span><span>//    }</span></div></div><div><div><div>96</div></div><div><span><span>            </span></span><span>//}</span></div></div><div><div><div>97</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>98</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>99</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><code>reAllocateBus4</code> 将重新分配结果的评判统计量从边的数量改为边的利用率，比单纯关注边数更有全局意义，实测效果也更好，收敛速度更快。但是其中有一个疑惑的地方，理论上来说边的利用率应越大越好，但实际上把接受重新分配结果的标准定为 <code>重新分配后的边的利用率&lt;重新分配前的边的利用率</code> 可以使成本大幅下降（但不能保证每次迭代成本递减），这个完全相反的逻辑是目前仍未想明白的。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>void</span><span> </span><span>reAllocateBus4</span><span>(</span><span>int</span><span><span> </span><span>HLim</span><span>) {</span></span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>    </span><span>int</span><span> </span><span>gap</span><span> </span><span>=</span><span> </span><span>max</span><span>(</span><span>int</span><span>(</span><span>0.025</span><span> </span><span>*</span><span> </span><span>T</span><span>), </span><span>20</span><span>);</span></div></div><div><div><div>4</div></div><div><span>    </span><span>if</span><span> (</span><span>gap</span><span> </span><span>&gt;</span><span> </span><span>T</span><span>)</span></div></div><div><div><div>5</div></div><div><span>        </span><span>return</span><span>;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>    </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>busIdx</span><span>(</span><span>gap</span><span>, </span><span>0</span><span>);</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>i</span><span> </span><span>+</span><span> </span><span>gap</span><span> </span><span>&lt;</span><span> </span><span>HLim</span><span>; </span><span>i</span><span> </span><span>=</span><span> </span><span>i</span><span> </span><span>+</span><span> </span><span>gap</span><span>) {</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>        </span><span>srand</span><span>(</span><span>42</span><span>);</span><span>  // 设置随机数种子</span></div></div><div><div><div>12</div></div><div><span>        </span><span>random_shuffle</span><span>(</span><span>totBusIdx</span><span>.</span><span>begin</span><span>(), </span><span>totBusIdx</span><span>.</span><span>end</span><span>());</span></div></div><div><div><div>13</div></div><div><span>        </span><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>i</span><span> </span><span>&lt;</span><span> </span><span>gap</span><span>; </span><span>++</span><span>i</span><span>) {</span></div></div><div><div><div>14</div></div><div><span>            </span><span>busIdx</span><span>[</span><span>i</span><span>] </span><span>=</span><span> </span><span>totBusIdx</span><span>[</span><span>i</span><span>];</span></div></div><div><div><div>15</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span>        </span><span>int</span><span> </span><span>oriEdgeNum</span><span> </span><span>=</span><span> </span><span>0</span><span>, </span><span>oriFullEdge</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>18</div></div><div><span>        </span><span>unordered_set</span><span>&lt;</span><span>int</span><span>&gt; </span><span>mark1</span><span>;</span></div></div><div><div><div>19</div></div><div><span>        </span><span>unordered_set</span><span>&lt;</span><span>int</span><span>&gt; </span><span>mark2</span><span>;</span></div></div><div><div><div>20</div></div><div><span>        </span><span>for</span><span> (</span><span>int</span><span> </span><span>j</span><span> </span><span>=</span><span> </span><span>i</span><span>; </span><span>j</span><span> </span><span>&lt;</span><span> </span><span>i</span><span> </span><span>+</span><span> </span><span>gap</span><span>; </span><span>++</span><span>j</span><span>) {</span></div></div><div><div><div>21</div></div><div><span>            </span><span>oriEdgeNum</span><span> </span><span>+=</span><span> </span><span>countEdgeNum</span><span>(</span><span>buses</span><span>[</span><span>busIdx</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>]].</span><span>path</span><span>, </span><span>mark1</span><span>);</span></div></div><div><div><div>22</div></div><div><span>            </span><span>oriFullEdge</span><span> </span><span>+=</span><span> </span><span>testEdgeFull</span><span>(</span><span>buses</span><span>[</span><span>busIdx</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>]].</span><span>path</span><span>, </span><span>mark2</span><span>);</span></div></div><div><div><div>23</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>24</div></div><div>
</div></div><div><div><div>25</div></div><div><span>        </span><span>vector</span><span>&lt;</span><span>vector</span><span>&lt;</span><span>int</span><span>&gt;&gt; </span><span>pathTmp1</span><span>(</span><span>gap</span><span>, </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt;());</span><span>     // 用于此后重新加载边</span></div></div><div><div><div>26</div></div><div><span>        </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>pileTmp1</span><span>(</span><span>gap</span><span>, </span><span>-</span><span>1</span><span>);</span></div></div><div><div><div>27</div></div><div><span>        </span><span>for</span><span> (</span><span>int</span><span> </span><span>j</span><span> </span><span>=</span><span> </span><span>i</span><span>, </span><span>busId</span><span>; </span><span>j</span><span> </span><span>&lt;</span><span> </span><span>i</span><span> </span><span>+</span><span> </span><span>gap</span><span>; </span><span>++</span><span>j</span><span>) {</span></div></div><div><div><div>28</div></div><div><span>            </span><span>busId</span><span> </span><span>=</span><span> </span><span>busIdx</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>];</span></div></div><div><div><div>29</div></div><div><span>            </span><span>pathTmp1</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>] </span><span>=</span><span> </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>pathTmp</span><span>;</span></div></div><div><div><div>30</div></div><div><span>            </span><span>pileTmp1</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>] </span><span>=</span><span> </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>pileId</span><span>;</span></div></div><div><div><div>31</div></div><div><span>            </span><span>reCoverNetwork</span><span>(</span><span>busId</span><span>, </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>pileId</span><span>);</span></div></div><div><div><div>32</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>33</div></div><div>
</div></div><div><div><div>34</div></div><div><span>        </span><span>int</span><span> </span><span>curEdgeNum</span><span> </span><span>=</span><span> </span><span>0</span><span>, </span><span>curFullEdge</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>35</div></div><div><span>        </span><span>bool</span><span> </span><span>findPath</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>36</div></div><div><span>        </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>pileTmp2</span><span>(</span><span>gap</span><span>, </span><span>-</span><span>1</span><span>);</span></div></div><div><div><div>37</div></div><div><span>        </span><span>for</span><span> (</span><span>int</span><span> </span><span>j</span><span> </span><span>=</span><span> </span><span>i</span><span> </span><span>+</span><span> </span><span>gap</span><span> </span><span>-</span><span> </span><span>1</span><span>, </span><span>busId</span><span>; </span><span>j</span><span> </span><span>&gt;=</span><span> </span><span>i</span><span>; </span><span>--</span><span>j</span><span>) {</span></div></div><div><div><div>38</div></div><div><span>            </span><span>busId</span><span> </span><span>=</span><span> </span><span>busIdx</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>];</span></div></div><div><div><div>39</div></div><div><span>            </span><span>loadBus</span><span>(</span><span>busId</span><span>, </span><span>false</span><span>);</span></div></div><div><div><div>40</div></div><div><span>            </span><span>pileTmp2</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>] </span><span>=</span><span> </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>pileId</span><span>;</span></div></div><div><div><div>41</div></div><div><span>            </span><span>curEdgeNum</span><span> </span><span>+=</span><span> </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>path</span><span>.</span><span>size</span><span>();</span></div></div><div><div><div>42</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>43</div></div><div><span>        </span><span>unordered_set</span><span>&lt;</span><span>int</span><span>&gt; </span><span>mark3</span><span>;</span></div></div><div><div><div>44</div></div><div><span>        </span><span>unordered_set</span><span>&lt;</span><span>int</span><span>&gt; </span><span>mark4</span><span>;</span></div></div><div><div><div>45</div></div><div><span>        </span><span>for</span><span> (</span><span>int</span><span> </span><span>j</span><span> </span><span>=</span><span> </span><span>i</span><span>; </span><span>j</span><span> </span><span>&lt;</span><span> </span><span>i</span><span> </span><span>+</span><span> </span><span>gap</span><span>; </span><span>++</span><span>j</span><span>) {</span></div></div><div><div><div>46</div></div><div><span>            </span><span>curEdgeNum</span><span> </span><span>+=</span><span> </span><span>countEdgeNum</span><span>(</span><span>buses</span><span>[</span><span>busIdx</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>]].</span><span>path</span><span>, </span><span>mark3</span><span>);</span></div></div><div><div><div>47</div></div><div><span>            </span><span>curFullEdge</span><span> </span><span>+=</span><span> </span><span>testEdgeFull</span><span>(</span><span>buses</span><span>[</span><span>busIdx</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>]].</span><span>path</span><span>, </span><span>mark4</span><span>);</span></div></div><div><div><div>48</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>49</div></div><div>
</div></div><div><div><div>50</div></div><div><span>        </span><span>if</span><span> (</span><span>curFullEdge</span><span> </span><span>*</span><span> </span><span>oriEdgeNum</span><span> </span><span>&lt;</span><span> </span><span>oriFullEdge</span><span> </span><span>*</span><span> </span><span>curEdgeNum</span><span>) {</span><span>  // 边的利用效率下降，接受迁移</span></div></div><div><div><div>51</div></div><div><span>            </span><span>continue</span><span>;</span></div></div><div><div><div>52</div></div><div>
</div></div><div><div><div>53</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>54</div></div><div><span>        </span><span>else</span><span> {</span><span>  // 否则，回复原状态</span></div></div><div><div><div>55</div></div><div><span>            </span><span>for</span><span> (</span><span>int</span><span> </span><span>j</span><span> </span><span>=</span><span> </span><span>i</span><span> </span><span>+</span><span> </span><span>gap</span><span> </span><span>-</span><span> </span><span>1</span><span>, </span><span>busId</span><span>; </span><span>j</span><span> </span><span>&gt;=</span><span> </span><span>i</span><span>; </span><span>--</span><span>j</span><span>) {</span><span>   // 把试图寻路时，造成的对网络的影响消除</span></div></div><div><div><div>56</div></div><div><span>                </span><span>busId</span><span> </span><span>=</span><span> </span><span>busIdx</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>];</span></div></div><div><div><div>57</div></div><div><span>                </span><span>reCoverNetwork</span><span>(</span><span>busId</span><span>, </span><span>pileTmp2</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>]);</span></div></div><div><div><div>58</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>59</div></div><div>
</div></div><div><div><div>60</div></div><div><span>            </span><span>for</span><span> (</span><span>int</span><span> </span><span>j</span><span> </span><span>=</span><span> </span><span>i</span><span>, </span><span>busId</span><span>; </span><span>j</span><span> </span><span>&lt;</span><span> </span><span>i</span><span> </span><span>+</span><span> </span><span>gap</span><span>; </span><span>++</span><span>j</span><span>) {</span><span>  // 重新加载所有的边</span></div></div><div><div><div>61</div></div><div><span>                </span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>nullVector</span><span>, </span><span>nullPath1</span><span>, </span><span>nullPath2</span><span>;</span></div></div><div><div><div>62</div></div><div><span>                </span><span>busId</span><span> </span><span>=</span><span> </span><span>busIdx</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>];</span></div></div><div><div><div>63</div></div><div><span>                </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>mutiplierId</span><span>.</span><span>swap</span><span>(</span><span>nullVector</span><span>);</span></div></div><div><div><div>64</div></div><div><span>                </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>path</span><span>.</span><span>swap</span><span>(</span><span>nullPath1</span><span>);</span></div></div><div><div><div>65</div></div><div><span>                </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>pathTmp</span><span>.</span><span>swap</span><span>(</span><span>nullPath2</span><span>);</span></div></div><div><div><div>66</div></div><div>
</div></div><div><div><div>67</div></div><div><span>                </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>pileId</span><span> </span><span>=</span><span> </span><span>-</span><span>1</span><span>;</span></div></div><div><div><div>68</div></div><div><span>                </span><span>buses</span><span>[</span><span>busId</span><span>].</span><span>curA</span><span> </span><span>=</span><span> </span><span>D</span><span>;</span></div></div><div><div><div>69</div></div><div><span>                </span><span>reloadBus</span><span>(</span><span>busId</span><span>, </span><span>pileTmp1</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>], </span><span>pathTmp1</span><span>[</span><span>j</span><span> </span><span>-</span><span> </span><span>i</span><span>]);</span></div></div><div><div><div>70</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>71</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>72</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>73</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>通过实际测试，我们最终选定了使用 <code>reAllocateBus4</code>，因为它拥有最好的全局性能与较快的收敛速度。迭代优化需要与删边协作使用，才能在迭代优化调整之后删除冗余边。由于 <code>reAllocateBus4</code> 不能确保每次迭代成本递减（但是一般都能减小到一个较低的成本后再发生小幅波动），所以后来增加了保存迭代过程中成本最低网络的功能，并且最后输出这个成本最低的网络。</p></section><section><h3>其他<a href="#其他"><span>#</span></a></h3><p>其他一些比较简单的算法（如添加放大器等）和上述主要算法的一些辅助函数在此不做说明，还有许多测试性的小优化方案如业务分配排序（根据起点终点分组或最短路径长度）由于应用场景有限未加入到主要代码中。</p></section></section>
<section><h2>初赛判题器<a href="#初赛判题器"><span>#</span></a></h2><p>由于迭代优化算法是在初赛结束之后才开始做的，线上判题入口已经关闭，便自己写了一个简单的判题器用于判断输出的结果是否合法、评判分数和计时，在这个过程中学到了一些有意思的东西。</p><section><h3>启动参数<a href="#启动参数"><span>#</span></a></h3><p>在使用命令行启动可执行文件时，<code>main()</code> 是可以传参的，如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> </span><span>main</span><span>(</span><span>int</span><span><span> </span><span>argc</span><span>, </span></span><span>char**</span><span><span> </span><span>argv</span><span>) {}</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><ul>
<li><code>argc</code> 为参数个数，要注意可执行文件名本身就算一个参数。</li>
<li><code>argv</code> 是参数列表，是一个字符串数组指针，可以从中读出每一个参数。</li>
</ul><blockquote><p>如在命令行运行时输入：<code>Judger.exe main.exe</code>，则 <code>argc</code> 为 <code>2</code>，<code>argv</code> 所指数组为 <code>["Judger.exe", "main.exe"]</code>。</p></blockquote></section><section><h3>管道通信<a href="#管道通信"><span>#</span></a></h3><p>这个判题器采用管道实现与解题程序的通信。由于管道是单工通信，故需要建立两条管道才能实现双工通信，但是由于比较繁琐最终放弃了双向通信，判题器只接收解题程序输出的结果，而输入则由用户输入。程序之间单向通信的管道的建立十分简单。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 读</span></div></div><div><div><div>2</div></div><div><span>FILE</span><span>*</span><span> </span><span>pipe</span><span> </span><span>=</span><span> </span><span>_popen</span><span>(</span><span>programName</span><span>, </span><span>"r"</span><span>);</span></div></div><div><div><div>3</div></div><div><span>// 写</span></div></div><div><div><div>4</div></div><div><span>FILE</span><span>*</span><span> </span><span>pipe</span><span> </span><span>=</span><span> </span><span>_popen</span><span>(</span><span>programName</span><span>, </span><span>"w"</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>通过这一行代码即可同时做到在命令窗口内拉起目标程序已经建立对应的读或写的管道。目标程序被拉起后会在同一个命令窗口中与主程序同时运行，若此时管道为读，目标程序的标准输入流就依然是命令窗口输入，标准输出则接到了管道上，可由主程序使用 <code>fscanf()</code> 读取；若此时管道为写，目标程序的标准输入流接到管道上，可由主程序使用 <code>fprintf()</code> 写入，而标准输出依然是命令窗口输出。</p></section></section>
<section><h2>复赛策略<a href="#复赛策略"><span>#</span></a></h2><p>复赛主要是增加了一个业务需要找出多条路径的需求，并且对这多条路径有一定约束。理论上来说只需在代码中增加寻找多条路径的处理方法，并且按约束条件在寻找多条路径时对已经选择过的边进行封锁即可简单解决，但是比赛的时候这么做却一直在超时。赛后在本地自造数据集后调试的时候发现，当前的策略存在某种问题，直接这样修改会导致加边数量巨大，使得网络复杂度快速上升，寻路算法的性能快速下降，从而导致超时。</p><p>从赛后复盘看来，应该优先给需要分配两条路径的业务（有约束）分配路径，并且采用新的加边策略，寻路算法使用双向 BFS 来提高在复杂网络下寻路的效率，才能较好的解决这个问题。</p></section>
<section><h2>成绩<a href="#成绩"><span>#</span></a></h2><p>初赛期间未使用迭代优化算法获得粤港澳上合赛区第三名，若加上迭代优化算法有望登顶。复赛由于在比赛的 4 个小时中未能解决超时问题未能出分，十分遗憾！</p></section>
<section><h2>总结<a href="#总结"><span>#</span></a></h2><p>团队比赛的优势在于可以集思广益，能有志同道合的人一起讨论问题、一起解决问题是十分幸福的一件事情，非常感谢强大的队友不断有新的想法去尝试。</p><p>虽然复赛没有出理想的成绩，但是借此机会来到了华为的欧洲小镇，坐着小火车感受了这一带的风景与氛围，在夕阳之下躺在广阔的草地上打滚，和华为工程师一起共进晚宴，探讨行业前沿信息……参赛体验十分不错，非常感谢华为光产品线提供的这次机会，明年再做追光者！</p><a href="https://github.com/WJD1005/HUAWEI-ControlRush2023" target="_blank"><div><div><div><div></div><div>WJD1005</div></div><div>/</div><div>HUAWEI-ControlRush2023</div></div><div></div></div><div>2023华为嵌入式软件大赛</div><div><div>—</div><div>—</div><div>no-license</div><span>C++</span></div></a></section>]]></content>
    </entry>
    <entry>
      <id>https://neb.kdns.fr/posts/huawei-code-craft-2023/</id>
      <title type="text">2023 华为软件精英挑战赛复盘</title>
      <published>2023-05-05T00:00:00.000Z</published>
      <updated>2023-05-05T00:00:00.000Z</updated>
      <author><name>星云质心</name></author>
      <link rel="alternate" href="https://neb.kdns.fr/posts/huawei-code-craft-2023/"/>
      <summary type="text">选手程序操控 4 个机器人执行前进、后退、旋转、购买、出售等动作来完成物品递送任务，同时赚取差价获得利润。在运行结束时，选手拥有的资金数即为最终分数，所获得的资金越高越好。</summary>
      <content type="html"><![CDATA[<section><h2>比赛简介<a href="#比赛简介"><span>#</span></a></h2><section><h3>比赛主页<a href="#比赛主页"><span>#</span></a></h3><p><a href="https://competition.huaweicloud.com/codecraft2023" target="_blank">2023 华为软件精英挑战赛——普朗克计划</a></p></section><section><h3>比赛题目<a href="#比赛题目"><span>#</span></a></h3><p>初赛：选手程序操控 4 个机器人执行前进、后退、旋转、购买、出售等动作来完成物品递送任务，同时赚取差价获得利润。在运行结束时，选手拥有的资金数即为最终分数，所获得的资金越高越好。</p><p>复赛：引入复杂固定障碍。</p><p>决赛：引入激光雷达，两队对抗战。</p><p>彩蛋题：引入激光探图机制，不提供地图数据。</p><blockquote><p>在这个彩蛋当中，没有对手，有的只是你不断的超越自己；也没有比赛奖励，有的只是你在攻克了一道道技术难题之后所收获的兴奋与成长。希望所有的参赛选手，能够喜欢赛题组精心准备的这份礼物。</p><p>——2023 软挑赛题组</p></blockquote></section><section><h3>赛题资料<a href="#赛题资料"><span>#</span></a></h3><ul>
<li><a href="https://bbs.huaweicloud.com/forum/thread-0225113791152139025-1-1.html" target="_blank">初赛练习赛</a></li>
<li><a href="https://bbs.huaweicloud.com/forum/thread-0219115001097335002-1-1.html" target="_blank">初赛正式赛</a></li>
<li><a href="https://bbs.huaweicloud.com/forum/thread-0276115433925333002-1-1.html" target="_blank">复赛练习赛</a></li>
<li><a href="https://bbs.huaweicloud.com/forum/thread-0217116396999188032-1-1.html" target="_blank">复赛正式赛</a></li>
<li><a href="https://bbs.huaweicloud.com/forum/thread-0298116469469619076-1-1.html" target="_blank">决赛练习赛</a></li>
<li><a href="https://bbs.huaweicloud.com/forum/thread-0232117504867893010-1-1.html" target="_blank">决赛正式赛</a></li>
<li><a href="https://bbs.huaweicloud.com/forum/thread-0232118049695936048-1-1.html" target="_blank">彩蛋题</a></li>
</ul><blockquote><p>彩蛋题资料中包含 SimpleDemo 源码，并且可以同时运行于初赛、复赛、决赛、彩蛋题。</p></blockquote></section></section>
<section><h2>初赛策略<a href="#初赛策略"><span>#</span></a></h2><p>初赛赛题需要考虑的情况不算复杂，所以使用的各项策略也十分简单，使用 Python 编程。</p><section><h3>运动控制<a href="#运动控制"><span>#</span></a></h3><p>因为机器人的运动并不是简单的线性运动，准确控制需要根据提供的机器人各项物理参数求解运动方程，并且给出的参数都是如电机最大扭矩之类的，而实际运动中电机扭矩是随运动幅度变化的，所以计算会比较复杂。为了避免复杂的运动控制计算（其实是不想做），我采用了最为简单的 PID 算法来控制机器人的旋转，实现后发现只要 P 的效果也足够用了（测试发现机器人运动摩擦力非常大，故振荡较小），所以最终实现起来非常简单，以下为核心代码。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span># 方向调整控制</span></div></div><div><div><div>2</div></div><div><span><span>expected_angle </span><span>=</span><span> </span><span>calculate_angle</span><span>(bot_id, table_id)  </span></span><span># 计算目标方向角</span></div></div><div><div><div>3</div></div><div><span># 目标方向和当前方向之差大于pi时需要转换</span></div></div><div><div><div>4</div></div><div><span>if</span><span><span> numpy.</span><span>abs</span><span>(expected_angle </span><span>-</span><span> bot[</span></span><span>'direction'</span><span><span>]) </span><span>&gt;</span><span> numpy.pi:</span></span></div></div><div><div><div>5</div></div><div><span>    </span><span># 当前朝向先做转换变到与目标方向同号</span></div></div><div><div><div>6</div></div><div><span>    </span><span># 当前朝向方向角为0不需要转换</span></div></div><div><div><div>7</div></div><div><span>    </span><span># 转换结果只在临时变量中用于计算偏差角，并不修改数据字典中的值</span></div></div><div><div><div>8</div></div><div><span>    </span><span>if</span><span> bot[</span><span>'direction'</span><span><span>] </span><span>&lt;</span><span> </span></span><span>0</span><span>:</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>bot[</span><span>'direction'</span><span><span>] </span><span>+=</span><span> </span></span><span>2</span><span><span> </span><span>*</span><span> numpy.pi</span></span></div></div><div><div><div>10</div></div><div><span>    </span><span>elif</span><span> bot[</span><span>'direction'</span><span><span>] </span><span>&gt;</span><span> </span></span><span>0</span><span>:</span></div></div><div><div><div>11</div></div><div><span><span>        </span></span><span>bot[</span><span>'direction'</span><span><span>] </span><span>-=</span><span> </span></span><span>2</span><span><span> </span><span>*</span><span> numpy.pi</span></span></div></div><div><div><div>12</div></div><div><span># 控制旋转速度，偏差角度越大角速度越大</span></div></div><div><div><div>13</div></div><div><span>if</span><span><span> expected_angle </span><span>-</span><span> bot[</span></span><span>'direction'</span><span><span>] </span><span>&lt;</span><span> </span></span><span>0</span><span>:</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>command[</span><span>'rotate'</span><span><span>][bot_id] </span><span>=</span><span> </span><span>-</span><span>min_rotate_velocity </span><span>+</span><span> angular_velocity_kp </span><span>*</span><span> (expected_angle </span><span>-</span><span> bot[</span></span><span>'direction'</span><span>])</span></div></div><div><div><div>15</div></div><div><span>elif</span><span><span> expected_angle </span><span>-</span><span> bot[</span></span><span>'direction'</span><span><span>] </span><span>&gt;</span><span> </span></span><span>0</span><span>:</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>command[</span><span>'rotate'</span><span><span>][bot_id] </span><span>=</span><span> min_rotate_velocity </span><span>+</span><span> angular_velocity_kp </span><span>*</span><span> (expected_angle </span><span>-</span><span> bot[</span></span><span>'direction'</span><span>])</span></div></div><div><div><div>17</div></div><div><span># 到达偏差角阈值以最大速度前进</span></div></div><div><div><div>18</div></div><div><span>if</span><span><span> numpy.</span><span>abs</span><span>(expected_angle </span><span>-</span><span> bot[</span></span><span>'direction'</span><span><span>]) </span><span>&lt;</span><span> start_move_angle_threshold:</span></span></div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>command[</span><span>'forward'</span><span><span>][bot_id] </span><span>=</span><span> max_forward_velocity</span></span></div></div><div><div><div>20</div></div><div><span># 否则以最小速度前进</span></div></div><div><div><div>21</div></div><div><span>else</span><span>:</span></div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>command[</span><span>'forward'</span><span><span>][bot_id] </span><span>=</span><span> min_forward_velocity</span></span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>可见核心就只是系数乘偏差角，即可得到还算能用的控制效果。</p><p>除此之外，还有一些用于辅助控制的代码不在此处列出，比如接近目的地时减速刹车，基本也是通过 P 算法来实现。</p></section><section><h3>避障<a href="#避障"><span>#</span></a></h3><p>避障是基于 VO 算法思想，随手写的一个简易避障算法。因为没有精确的运动控制，只能沿用简单的 P 算法控制，再加上这是简单的单目标避障，最终效果并不好（特别是一个机器人跟在另一个机器人背后同向前进时）。以下是核心代码。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span># 计算碰撞区</span></div></div><div><div><div>2</div></div><div><span><span>collision_area_half_angle </span><span>=</span><span> numpy.</span><span>arcsin</span><span>(</span></span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>(bot_1_radius </span><span>+</span><span> bot_2_radius) </span><span>/</span><span> distance_list[bot_id_2])  </span><span># 碰撞区半角</span></div></div><div><div><div>4</div></div><div><span># 适当增加碰撞区半角，但不超出最大值</span></div></div><div><div><div>5</div></div><div><span>if</span><span><span> collision_area_half_angle </span><span>*</span><span> collision_area_half_angle_kp </span><span>&gt;</span><span> numpy.pi </span><span>/</span><span> </span></span><span>2</span><span>:</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>collision_area_half_angle </span><span>=</span><span> numpy.pi </span><span>/</span><span> </span><span>2</span></div></div><div><div><div>7</div></div><div><span>else</span><span>:</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>collision_area_half_angle </span><span>*=</span><span> collision_area_half_angle_kp</span></div></div><div><div><div>9</div></div><div><span><span>collision_area_center_angle </span><span>=</span><span> </span><span>calculate_angle_between_bot</span><span>(bot_id_1, bot_id_2)  </span></span><span># 碰撞区中心方向角</span></div></div><div><div><div>10</div></div><div><span><span>collision_area_left_boundary_angle </span><span>=</span><span> collision_area_center_angle </span><span>+</span><span> collision_area_half_angle  </span></span><span># 碰撞区左边界方向角</span></div></div><div><div><div>11</div></div><div><span><span>collision_area_right_boundary_angle </span><span>=</span><span> collision_area_center_angle </span><span>-</span><span> collision_area_half_angle  </span></span><span># 碰撞区右边界角</span></div></div><div><div><div>12</div></div><div><span># 计算机器人1相对于机器人2的速度</span></div></div><div><div><div>13</div></div><div><span><span>bot_1_relative_velocity_x </span><span>=</span><span> bot_1[</span></span><span>'linear_velocity'</span><span>][</span><span>0</span><span><span>] </span><span>-</span><span> bot_2[</span></span><span>'linear_velocity'</span><span>][</span><span>0</span><span>]  </span><span># x方向相对速度</span></div></div><div><div><div>14</div></div><div><span><span>bot_1_relative_velocity_y </span><span>=</span><span> bot_1[</span></span><span>'linear_velocity'</span><span>][</span><span>1</span><span><span>] </span><span>-</span><span> bot_2[</span></span><span>'linear_velocity'</span><span>][</span><span>1</span><span>]  </span><span># y方向相对速度</span></div></div><div><div><div>15</div></div><div><span><span>bot_1_relative_velocity_angle </span><span>=</span><span> numpy.</span><span>arctan2</span><span>(bot_1_relative_velocity_y,</span></span></div></div><div><div><div>16</div></div><div><span><span>                                                </span></span><span>bot_1_relative_velocity_x)  </span><span># 相对速度方向</span></div></div><div><div><div>17</div></div><div><span># 如果相对速度方向和碰撞区中心方向角之差大于pi（例如碰撞区是负角度，但相对速度方向在其+2pi后的正角度区间内）</span></div></div><div><div><div>18</div></div><div><span>if</span><span><span> numpy.</span><span>abs</span><span>(bot_1_relative_velocity_angle </span><span>-</span><span> collision_area_center_angle) </span><span>&gt;</span><span> numpy.pi:</span></span></div></div><div><div><div>19</div></div><div><span>    </span><span># 变换到同号区间</span></div></div><div><div><div>20</div></div><div><span>    </span><span>if</span><span><span> bot_1_relative_velocity_angle </span><span>&lt;</span><span> </span></span><span>0</span><span>:</span></div></div><div><div><div>21</div></div><div><span><span>        </span></span><span>bot_1_relative_velocity_angle </span><span>+=</span><span> </span><span>2</span><span><span> </span><span>*</span><span> numpy.pi</span></span></div></div><div><div><div>22</div></div><div><span>    </span><span>elif</span><span><span> bot_1_relative_velocity_angle </span><span>&gt;</span><span> </span></span><span>0</span><span>:</span></div></div><div><div><div>23</div></div><div><span><span>        </span></span><span>bot_1_relative_velocity_angle </span><span>-=</span><span> </span><span>2</span><span><span> </span><span>*</span><span> numpy.pi</span></span></div></div><div><div><div>24</div></div><div><span># 如果相对速度方向在碰撞区内则会发生碰撞（恰巧在边界会相切，所以也避免），需要避让</span></div></div><div><div><div>25</div></div><div><span>if</span><span><span> collision_area_right_boundary_angle </span><span>&lt;</span><span> bot_1_relative_velocity_angle </span><span>&lt;</span><span> collision_area_left_boundary_angle:</span></span></div></div><div><div><div>26</div></div><div><span>    </span><span># 检测离哪边边界近就往哪边转，直接和中心方向角比较即可</span></div></div><div><div><div>27</div></div><div><span>    </span><span># 离右边界近</span></div></div><div><div><div>28</div></div><div><span>    </span><span>if</span><span><span> bot_1_relative_velocity_angle </span><span>&lt;</span><span> collision_area_center_angle:</span></span></div></div><div><div><div>29</div></div><div><span><span>        </span></span><span>command[</span><span>'rotate'</span><span><span>][bot_id_1] </span><span>=</span><span> min_rotate_velocity </span><span>+</span><span> angular_velocity_kp </span><span>*</span><span> (</span></span></div></div><div><div><div>30</div></div><div><span><span>                </span></span><span>collision_area_right_boundary_angle </span><span>-</span><span> bot_1_relative_velocity_angle)</span></div></div><div><div><div>31</div></div><div><span>    </span><span># 离左边界近</span></div></div><div><div><div>32</div></div><div><span>    </span><span>elif</span><span><span> bot_1_relative_velocity_angle </span><span>&gt;</span><span> collision_area_center_angle:</span></span></div></div><div><div><div>33</div></div><div><span><span>        </span></span><span>command[</span><span>'rotate'</span><span><span>][bot_id_1] </span><span>=</span><span> min_rotate_velocity </span><span>+</span><span> angular_velocity_kp </span><span>*</span><span> (</span></span></div></div><div><div><div>34</div></div><div><span><span>                </span></span><span>collision_area_left_boundary_angle </span><span>-</span><span> bot_1_relative_velocity_angle)</span></div></div><div><div><div>35</div></div><div><span>    </span><span># 恰好位于中间</span></div></div><div><div><div>36</div></div><div><span>    </span><span>else</span><span>:</span></div></div><div><div><div>37</div></div><div><span>        </span><span># 查看目前的角速度方向，往当前已有的角速度方向转，角速度为0则默认顺时针旋转</span></div></div><div><div><div>38</div></div><div><span>        </span><span># 角速度大于0，即逆时针旋转中</span></div></div><div><div><div>39</div></div><div><span>        </span><span>if</span><span> bot_1[</span><span>'angular_velocity'</span><span><span>] </span><span>&gt;</span><span> </span></span><span>0</span><span>:</span></div></div><div><div><div>40</div></div><div><span><span>            </span></span><span>command[</span><span>'rotate'</span><span><span>][bot_id_1] </span><span>=</span><span> min_rotate_velocity </span><span>+</span><span> angular_velocity_kp </span><span>*</span><span> (</span></span></div></div><div><div><div>41</div></div><div><span><span>                    </span></span><span>collision_area_left_boundary_angle </span><span>-</span><span> bot_1_relative_velocity_angle)</span></div></div><div><div><div>42</div></div><div><span>        </span><span># 角速度小于0，即顺时针旋转中</span></div></div><div><div><div>43</div></div><div><span>        </span><span>elif</span><span> bot_1[</span><span>'angular_velocity'</span><span><span>] </span><span>&lt;</span><span> </span></span><span>0</span><span>:</span></div></div><div><div><div>44</div></div><div><span><span>            </span></span><span>command[</span><span>'rotate'</span><span><span>][bot_id_1] </span><span>=</span><span> min_rotate_velocity </span><span>+</span><span> angular_velocity_kp </span><span>*</span><span> (</span></span></div></div><div><div><div>45</div></div><div><span><span>                    </span></span><span>collision_area_right_boundary_angle </span><span>-</span><span> bot_1_relative_velocity_angle)</span></div></div><div><div><div>46</div></div><div><span>        </span><span># 角速度为0，默认顺时针旋转</span></div></div><div><div><div>47</div></div><div><span>        </span><span>else</span><span>:</span></div></div><div><div><div>48</div></div><div><span><span>            </span></span><span>command[</span><span>'rotate'</span><span><span>][bot_id_1] </span><span>=</span><span> min_rotate_velocity </span><span>+</span><span> angular_velocity_kp </span><span>*</span><span> (</span></span></div></div><div><div><div>49</div></div><div><span><span>                    </span></span><span>collision_area_right_boundary_angle </span><span>-</span><span> bot_1_relative_velocity_angle)</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>可见算法依然十分暴力简单，如果有更好的运动控制算法，避障算法也不至于做得这么简陋（算法其实后期优化过，但测试效果不好故没有保留）。至于上文所说的当一个机器人跟在另一个机器人背后同向而行时会出现问题，就是在这种情况下若被判定为会碰撞，两个机器人都会执行避让（实际上前面的机器人并不需要避让，甚至后面的也可能不需要避让），然后两个机器人都开始偏离目标角度并减速，最终导致两机器人相距很近相互纠缠着低速前进，直到分开。这个问题可以在出现这种情况时禁止前面的机器人执行避障来解决。</p></section><section><h3>任务分配<a href="#任务分配"><span>#</span></a></h3><p>任务分配的基础策略是根据产品优先级：<code>7 &gt; (4, 5, 6) &gt; (1, 2, 3)</code>，当机器人空闲的时候会按照此优先级去购买产品。对于同等优先级内的产品，采用的策略是机器人从当前位置到购买工作台的距离与从购买工作台到出售工作台的距离之和最短来选取购买和出售两个目标工作台。</p><p>除此之外还有几个强化策略，分别是抢占购买、原地购买、动态优先级和禁用工作台。</p><ul>
<li>
<p><strong>抢占购买</strong>是当某机器人空闲时发现某已分配的任务由它来执行比原执行该任务的机器人剩余路径短得多，则抢占该任务执行，被抢占机器人重新分配任务。</p>
</li>
<li>
<p><strong>原地购买</strong>是当机器人出售完物品后，其所在工作台有需要购买的产品已生产完毕或剩余生产时间很短，则原地购买该工作台的产品去出售，这个策略也带有抢占性质。</p>
</li>
<li>
<p><strong>动态优先级</strong>（正式赛加入）是在某些 4、5、6 物品合成非常不平均的情况下使用的策略，通过改变产品优先级来优先分配合成当前数量较少的物品的任务，达到平衡 4、5、6 物品数量的目的，有利于物品 7 的合成。</p>
</li>
<li>
<p><strong>禁用工作台</strong>（正式赛加入）是当工作台数量过多时使用的策略，用于避免合成原料过于分散。虽然可以通过判断工作台原材料格情况来决定先出售到哪个工作台，以此使原料更集中，但是实际测试中发现通过简单直接的禁用部分工作台的方法即可解决这个问题并得到不错的效果。</p>
</li>
</ul></section><section><h3>正式赛针对性优化<a href="#正式赛针对性优化"><span>#</span></a></h3><p>动态优先级和禁用工作台策略实际上就是针对正式赛地图优化的产物，除此之外还有还有其他针对性的小措施，如调整出售工作台类别等，基本都没有通用性。</p></section></section>
<section><h2>成绩<a href="#成绩"><span>#</span></a></h2><p>初赛正式赛四张图分数分别是 684678、771579、824985、641533，共 2922775 分，位列粤港澳赛区第 58 名（粤港澳真的太卷了啊）。</p></section>
<section><h2>总结<a href="#总结"><span>#</span></a></h2><p>不得不说，今年软挑的题目十分有趣好玩，赛题组也十分用心。看着小机器人从跌跌撞撞不会走路到丝滑移动甚至漂移避障，每一次改进策略后分数的提升都能给我带来一阵喜悦。</p><p>第一次参加软挑，没什么经验，大部分算法纯属自己瞎整，各种不想写复杂算法的妥协如滚雪球般慢慢积累，最终很多地方不得不一再妥协、简化，导致效果并不好，这是一大败笔。基础算法是一定要做好的，否则会影响后续各种算法的发挥。</p><p>总的来说，参赛体验十分不错，明年再战！</p><a href="https://github.com/WJD1005/HUAWEI-CodeCraft2023" target="_blank"><div><div><div><div></div><div>WJD1005</div></div><div>/</div><div>HUAWEI-CodeCraft2023</div></div><div></div></div><div>Repository details unavailable</div><div><div>—</div><div>—</div><div>—</div><span>Unavailable</span></div></a></section>]]></content>
    </entry>
    <entry>
      <id>https://neb.kdns.fr/posts/cat-ears/</id>
      <title type="text">猫耳朵</title>
      <published>2023-05-01T00:00:00.000Z</published>
      <updated>2023-05-01T00:00:00.000Z</updated>
      <author><name>星云质心</name></author>
      <link rel="alternate" href="https://neb.kdns.fr/posts/cat-ears/"/>
      <summary type="text">太阳完全下沉到了城市的另一边，污血色的晚霞像是天空红肿的伤口，慢慢化作紫绀色，像是黄昏的尸斑。</summary>
      <content type="html"><![CDATA[<blockquote><p>本文写作风格学习自 <a href="https://space.bilibili.com/2304371/" target="_blank"><strong>水滴酱</strong></a>，封面由 AI 生成。</p></blockquote>
<section><h2>1<a href="#1"><span>#</span></a></h2><p>太阳完全下沉到了城市的另一边，污血色的晚霞像是天空红肿的伤口，慢慢化作紫绀色，像是黄昏的尸斑。</p><p>“你到底去哪了？”我像具行尸走肉一样游荡在大街上，身旁的路人像看到怪物一般，瞳孔里充满惊恐，拉开与我的距离快速走过。</p><p>嘀嘀嘀，我的手机响了起来。</p><p>我颤抖着从口袋里摸出手机，打开手机——那是我用她照片做的锁屏壁纸。手机里的她红着脸，静静地看着我。她那蓝黑色的瞳孔，深邃得像要把一切吸进去。</p><p>再也忍不住了，我看也没看就按下了电源键，终于让这刺耳无比的闹钟声停了下来。</p><p>头顶两旁的霓虹灯病变般地分裂，在黑夜中蔓延，这将死般的灯光却丝毫不能照亮我的身躯。</p><p>“你到底去哪了……”我像个疯子一般重复着这句话。</p><p>下雨了。</p><p>我停止了发出声音，热闹的街道仿佛顷刻消失，随后而来的是一片寂静，只听得见那仿佛永不停息的污浊雨水在四周轰鸣。</p></section>
<section><h2>2<a href="#2"><span>#</span></a></h2><p>第一次遇见她的时候，也是在这条下雨的街道上。</p><p>“为什么又要离开我……”</p><p>已经不知道是第几次经历分手的痛苦了，我算是彻底死心了，在路边的夜宵摊上喝得大醉。</p><p>踉跄地走到街上，一滴滴冰冷的触感打在我身上。没带伞，就这么回去吧。	啪嗒，我一脚踩到一个水坑上，本来积水上反射着的暗淡的霓虹灯的光芒被我打散，扭曲，旋转，积水里的世界就这样碎裂，暧昧摇曳，迷幻绝望。</p><p>从口袋里摸出一盒烟，打开盒盖挑了一支叼在嘴上。雨里点烟有点困难，但还是点着了。为了不让它被这不懂事的雨淋湿，我深深地吸了一口，眼前那点橙红色的微弱荧光猛地变亮，随后又慢慢暗淡下去，正如小时候和父母一起在河岸边看的烟花一样。</p><p>十几年前在我很小的时候，我的父母因故去世，后来被人收养长大。如今我一个人远离家乡在外打工，陪伴我的只有老板的辱骂、房东的催租、朋友的嘲讽，如今又被女朋友抛弃。我真的一无所有。</p><p>“……果然我还是没用啊。”</p><p>好像喝得有点太多了，我的胃里翻江倒海，糜烂腐臭的内容物伴随着浓稠的黄绿色液体从我的食道涌出，烟也掉到了地上，失去最后那一点微光。</p><p>我难受得捂着自己的胸膛。</p><p>咚，咚，咚……</p><p>这或许是我活在这个世界上的唯一证明吧。</p><p>吐了许久，我抬起头准备继续走回家。</p><p>嗯？</p><p>在惨白的 LED 灯光下，一个头戴黑色猫耳装饰，飘着一头水蓝色头发，身穿黑色外套，下摆露出一小截短裙的少女正看向我的方向，身后好像还有一条垂至小腿的黑色尾巴在随风摇摆。她表情看上去很茫然，蓝黑色瞳孔中反射着昏黄的路灯。雨滴滴落在她娇嫩的脸上，像是一滴滴泪珠，发丝也被黏在了脸上。</p><p>当我回过神来时，我已经走到了少女面前。</p><p>似乎是感受到了我的视线，她望向我的眼睛。</p><p>“可以带我回家吗？”</p></section>
<section><h2>3<a href="#3"><span>#</span></a></h2><p>吱呀。</p><p>我关上了出租屋的房门。</p><p>房间内一览无余，仅有必用的几件家具。</p><p>少女就这样怔怔地站在这小小房间的正中心。灯泡的灯光从她的头顶洒落，宛同圣女。</p><p>圣洁。</p><p>与初遇时不同，此时她蓝宝石般的眼睛充满光泽，清澈无比。</p><p>少女的体香就像腐烂的水果，这股甜腻的香味逐渐氤氲在这小小的空间中，越发令人沉迷其中无法自拔。</p><p>我和她的距离不到 30 厘米。我开始后悔了，借着这酒劲我干了什么事啊，拐骗少女回家可是犯法的啊。</p><p>少女突然抬起头，凝视着我的眼睛。她的眼睛中映出了我这张憔悴又丑陋的脸。我实在是受不了这目光，躲开了她的视线，眼睛看向了她的头顶。</p><p>这猫耳头饰做得真精致啊，就跟真的一样……嗯？这也太真了吧？！</p><p>被眼前这一幕吓到的我往后退了两步，脚踩到了扔在地上的玻璃啤酒瓶，脚直接向前做了个加速运动，而上半身被牛顿留在了原地。</p><p>我摔倒了在她面前。</p><p>头砸在了墙上，摔得好痛。</p><p>我惊恐地看着她，但后脑勺却传来一阵睡意，我的眼睛不受控制地合上，在视野剩下一条线时，我看到了她的嘴角微微上翘，但又渐渐变成淡淡的哀伤。</p></section>
<section><h2>4<a href="#4"><span>#</span></a></h2><p>后脑勺传来一阵痛感，但仿佛枕在柔软的云朵之上，那是我未曾感受过的舒适。</p><p>我强硬地与刺眼的灯光作斗争，缓缓地睁开眼睛。</p><p>那是一片蓝色，天空？</p><p>在短暂的失明后，那个少女出现在我的眼前，她长长的蓝色发尾刚好垂到我的脸颊上，弄出阵阵痒意。少女的香味让我更加迷失其中。</p><p>这角度，就是膝枕吧……没想到我这个废物的一生也有这样美好的瞬间啊……</p><p>突然，我的脑海中浮现出晕倒之前看到的画面——两个无比真实的猫耳朵长在这个少女头上。我的眼睛再次充满惊恐，而她的眼睛始终凝视着我，我甚至能在她眼睛中看到我现在这狼狈样。不知道是被吓到还是对现在这种美妙感受的迷恋，我的身体一点动作都没有。她嘴角再次勾出那一抹轻轻的笑意，猛地弯下腰，她的脸猛地贴近，近到能感受到彼此的呼吸。</p><p>“我确实是只猫哦~”</p><p>“喵~”</p><p>窗外的雨还在下着，狂躁的风裹挟着摇曳的雨幕，拍打着缺了一角的窗玻璃，感觉随时都要碎裂。窗外天旋地转，整座城市仿佛都在扭曲，旋转，扭曲，旋转……</p></section>
<section><h2>5<a href="#5"><span>#</span></a></h2><p>猫娘——</p><p>不怎么混二次元的我的脑中冒出了这个词。</p><p>传说中化作人形的猫？可是这东西真的现实存在吗？</p><p>管他呢，有这样的美少女陪着你还不知足？</p><p>……</p><p>脑内逐渐变得浓稠起来，又突然被稀释。</p><p>……</p><p>我艰难地动了动眼皮，尝试睁开了眼睛。原来我睡在了床上啊。</p><p>下一刻，我突然意识到了我胸上的被子仿佛重了千斤，但是十分柔软，并且异常温暖……</p><p>是那个少女。</p><p>她就静静地趴在我身上。</p><p>温柔而缓慢的呼吸。</p><p>微弱而规律的心跳。</p><p>我贪恋着这份从来没有感受过的温暖，似乎要把我融化在其中。我腾出两只手轻轻把她抱在怀中，似乎接受了她的存在。</p><p>她头顶上两只毛茸茸的耳朵突然颤了一颤。</p><p>“你在哭吗？”少女突然开口，这慵懒的声线却异常可爱，我不禁起了一身鸡皮疙瘩。</p><p>“没……没哭啊。”刚说出这句话，我就感觉到，我的枕头似乎是湿的。</p><p>嗯？好像我的衣服也是湿的。</p><p>“哭的是你吧？”我轻声问道。</p><p>两只猫耳朵又颤了一颤，随后轻轻起身，两只手支撑在床上，她那可爱娇嫩的脸就这么悬在我的脸上方。</p><p>好近。</p><p>少女脸两旁天蓝色的头发就这样顺着我的脸两旁下垂，仿佛给我们两个脸庞之间降下了一道帷幕，形成了一个只有我们两个人的私密空间。</p><p>她蓝色的眼睛中映出我的脸，随后突然变得暗淡无光，同万丈深渊一般，似乎要把面前的我和这小小的空间吸入。</p><p>少女什么都没说，便又重新趴在我的胸膛上。</p><p>“你想知道我为什么哭吗？”</p><p>“嗯。”</p><p>“很久以前，我的主人非常疼爱我，会给我做好吃的，会和我玩，会和我去看烟花……”</p><p>……</p><p>“可是后来，他们性情大变，我却成为了他们迁怒的对象，发泄的工具……”</p><p>……</p><p>说了很久以后，她开始啜泣起来。两只猫耳朵一抖一抖，那娇怜的样子，让我心疼。</p><p>“……那你没有反抗过吗？”我从嘴里艰难地挤出了一句话，但下一刻就觉得这个问题问得很傻瓜。</p><p>“不会的哦。像我们这种物种，都知道自己相对锦衣玉食的生活是靠着绝世的容颜和温顺的性情从主人那换来的。如果反抗的话……或许连在社会上最后的保护都没有了呢……”</p><p>“但是他们越来越变本加厉，把我扔到外面，就这样抛弃我了。或许我们本该就是这样被用完即弃的吧……”</p><p>用完即弃……</p><p>后面的故事就是在那下雨的街道上遇上了我并且被我带回家。</p><p>“你就不怕我也是这样的人吗？”我又不小心问了一个直男问题。</p><p>少女沉默了一会。</p><p>“不会的哦~”</p><p>“我在你的眼睛里看到了和他们不一样的东西~”</p><p>说实话，那只是我失恋后绝望痛苦的眼神罢了。</p><p>“我本不想再找一个新家了，可是我……看到了你，你的眼睛里满是痛苦与悲伤，而且凝视我时，有一种……压抑不住的同情与怜爱。”</p><p>“你又为什么哭呢？”</p><p>少女用双手把自己的身体撑起来从我身上离开，然后顺势倒在我的身侧，像恋人一样，把我抱入她那温暖的怀中。</p><p>“我……”</p></section>
<section><h2>6<a href="#6"><span>#</span></a></h2><p>“……就是这样罢了。”</p><p>少女一直把我环抱在她的怀中，任由太阳升得越来越高，阳光洒落在我们两人身上。</p><p>我试图压抑着自己的情绪，可眼泪还是不争气的往外流。</p><p>太羞耻了啊，我居然在一个女孩子的怀里哭。</p><p>少女轻轻笑着，抽出手帮我擦去眼角剩余的眼泪，又将我紧紧抱在怀中。</p><p>“你已经很优秀了哦~”</p><p>从她柔软身体上传来的温暖，让我从来没有感受过如此的安心。</p><p>“让我们开始新的生活吧喵~”</p><p>两只猫耳朵直直地竖了起来。</p></section>
<section><h2>7<a href="#7"><span>#</span></a></h2><p>我用我那蹩脚的厨艺，在被油烟熏得焦黄的厨房里，做了两份“人体生命体征保持餐”。没错，仅仅只是能吃而已，味道什么的就不要管啦。</p><p>少女正乖巧地坐在餐桌旁的椅子上，黑色的尾巴高高竖起。</p><p>我把两份饭端了出来，推一份到她面前，然后坐在了她对面。</p><p>她低下头闻了一闻，然后尝试性地吃了一口。</p><p>“喵！好难吃！”</p><p>这一瞬间我有点无地自容，没想到吐槽会来得这么快而且这么直白。</p><p>大概是看到我微妙的表情，少女又低下头去继续吃了。嘴上说着嫌弃，身体还是很诚实的嘛！</p><p>等我们两个都吃完以后，她直勾勾地盯着我的眼睛。</p><p>“以后还是我来做饭吧喵。”</p><p>欸？还有这等好事？我立马就答应了，作为交换我答应了她每天晚上要陪她玩。</p><p>她真的好可爱。</p><p>看着她，我突然想到了一件事。</p><p>我慢慢靠近了她。</p><p>我伸出了我的手，慢慢靠近她的侧脸。</p><p>她的脸微微泛红，眼睛躲开了我的视线。</p><p>我轻轻地触碰到了她那嫩滑的侧脸，温柔地抚摸着她的脸颊，然后轻轻撩起了她侧脸的那一撮蓝发……</p><p>“真的有四只耳朵！！”</p><p>我没忍住惊呼出来，猫娘到底有四只耳朵还是两只耳朵的事情之前已经困扰我很久了。</p><p>少女白了我一眼，红红的脸颊看着似乎有点生气。</p><p>“信不信我挠你！”</p><p>她作势要挠我，被我一下躲开。然后一人一猫就这样扭打在了一起，轻松的气氛充满了整个房间。</p></section>
<section><h2>8<a href="#8"><span>#</span></a></h2><p>接下来的几天，我逐渐适应了有她在我身边的生活。</p><p>早上上班前能吃到热腾腾的早餐，晚上下班回到家有人欢迎并且做好了一桌子菜等着我回来，闲下来以后陪她玩一会……</p><p>我从未感觉生活如此美好。</p><p>一天我下班后去了医院看医生，因为最近几天有时头疼得厉害。医生给我开了一瓶新药，我便直接回家了。</p><p>“欢迎回家喵~”推开门少女依然像往常一样站在门口迎接我。</p><p>我摸了摸她的头，两只耳朵即时直立了起来，看起来好有精神呢。</p><p>和她一起吃完饭，我把今晚要吃的药吃下，然后像往常一样陪她玩。原来猫娘也喜欢逗猫棒啊。</p><p>为了不会忘记吃药，我在手机上调好了闹钟，每到吃药时间闹钟就会响起，这样就不会忘啦。</p><p>到了睡觉时间，她像往常一样缩到我的怀里。</p><p>好暖，好幸福。</p><p>但突然间一种郁闷感浮上我的心头。我在想，会不会一旦接触过这种温暖，我就再也回不去了呢？</p><p>少女也似乎察觉了我的异样。</p><p>“人类真奇怪，眼前明明还能看到微弱烛光，却还要为将来的黑暗提前感到害怕。”</p><p>少女的话安抚了我。至少我现在是幸福的，未来，管他呢。</p><p>我轻轻抱着她，慢慢睡着了。</p></section>
<section><h2>9<a href="#9"><span>#</span></a></h2><p>这几天不知道为什么，我们两个之间的感觉似乎有点低气压。</p><p>她还是会像往常一样欢迎下班的我回家，给我做饭，但是好像和往常又有点不同，两只耳朵经常是耷拉着的。</p><p>我试图通过摸她头和用逗猫棒逗她来让她精神点，有点用，但过不了多久又会变得无神。</p><p>今天我因为剧烈的头疼和头晕在公司请了一天假，她一直在我身边照顾着我。</p><p>“还是先睡觉休息会吧喵。”</p><p>我躺在床上，在她温柔的抚摸之下，听着她柔弱的呼吸声迷迷糊糊地睡着了。</p><p>不知道睡了多久，我被手机的闹钟吵醒。</p><p>我睁开粘连在一起的眼皮摸到了手机把闹钟关掉。</p><p>奇怪，她居然没有在床边陪我。</p><p>我顶着混乱的脑子站了起来，走出去看看这猫在干什么。</p><p>扫视了一眼，我的心开始紧张起来——她不见了。</p><p>从未有过如此崩溃的感觉，我两腿一软，一屁股坐在了地上。我全身颤抖，不断在地上蠕动。</p><p>好痛，像是身体裂开了一样。</p><p>“不会的……不会的，她一定只是出去了……”我嘴唇不断抖出这句话。</p><p>我要出去找她。</p></section>
<section><h2>10<a href="#10"><span>#</span></a></h2><p>一天……</p><p>两天……</p><p>三天……</p><p>日日夜夜，不知疲倦。</p><p>不断往复，夜以继日。</p><p>“你到底去哪了……”</p><p>手机响起我也无心停下，手无情地摸到电源键关掉。我心里只有一个声音——快点找到她。</p><p>我的头晕头痛又发作了，可是为了她，我不能停下。</p><p>日日夜夜，夜以继日。</p><p>如是往复，永不停歇。</p><p>究竟已经过去多少天了？</p><p>我只知道我依然没找她。</p></section>
<section><h2>11<a href="#11"><span>#</span></a></h2><p>下雨了。</p><p>我停止了发出声音，热闹的街道仿佛顷刻消失，随后而来的是一片寂静，只听得见那仿佛永不停息的污浊雨水在四周轰鸣。</p><p>又走到了那个熟悉的地方，我无力地望向第一次遇见她的那个方向。</p><p>会有奇迹吗？</p><p>在惨白的 LED 灯光下，一个头戴黑色猫耳装饰，飘着一头水蓝色头发，身穿黑色外套，下摆露出一小截短裙的少女正看向我的方向，身后好像还有一条垂至小腿的黑色尾巴在随风摇摆。</p><p>我的脑袋顿时炸开。</p><p>和那天一模一样。</p><p>我欣喜地朝着她的方向跑去，但她也一转身，向黑暗中跑去。</p><p>“等等我！”</p><p>我在她身后穷追不舍，绝对不能让她跑掉。</p><p>少女窜进了一栋楼里，迅速走进电梯按下楼顶的按钮。</p><p>“陪我到楼顶看烟花哦~”</p><p>我没能赶上电梯，电梯门最后的一丝缝隙砰的一声关上。</p><p>楼梯，快跑。</p><p>我感觉到我的肺就像一个被人强行吹起的气球，时时刻刻快要炸裂了。</p><p>终于跑到楼顶了，我大口喘着粗气。</p><p>砰——</p><p>一阵低沉的爆破音传到我的鼓膜。</p><p>我定定地看着站在楼顶边缘的她，她的眼瞳已经重新充满神采。</p><p>我慢慢地靠近她，一同凝视着这七彩流转的夜空。眼睛虚焦着向远方望去，万家灯火、蜿蜒车流、缤纷焰火，种种颜色化作浑圆不清的色块，映亮了我心中的空虚。</p><p>少女转过头来望着我，她的眼睛还是那么的清澈。</p><p>“要和我永远在一起吗？”</p><p>砰！！！——</p><p>象征着烟花表演结束的巨型烟花窜上天幕，直穿云霄，绽放的那一刻，是如此耀眼，照亮了整个夜空。短暂的美好很快就过去了，眼前的世界又逐渐的暗了下来。</p><p>灿烂只是一时的，黑夜才是永恒的。</p><p>她牵起了我的手，眼睛里倒映着我的模样——不知道多少天的高强度寻找，让我失神疲惫这个地步。</p><p>“要吗？”少女再次发出提问。</p><p>“要！”我的眼神里充满坚定，用力握住她的手。毕竟这样操蛋的生活，没了她又有什么意义呢。</p><p>夜晚的微风愈发浓稠，我在这浓稠液体中感到浮力越来越大，双脚离开了地面。</p><p>“让我们开始新的生活吧喵~”</p></section>
<section><h2>12<a href="#12"><span>#</span></a></h2><p>一栋高楼发生了一男子坠亡事件，楼下现场拉上了警戒线，一群警察正在调查死者。</p><p>死者头戴着一对黑色猫耳头饰，腰间绑了一根 cosplay 用的黑色猫尾巴。</p><p>警察 A：“看看死者身上有没有什么物品吧。”</p><p>警察 B 摸了摸死者口袋，掏出了屏幕已经粉碎但还能正常点亮的手机，锁屏壁纸好像是死者自己的照片，也是戴着猫耳头饰。</p><p>嘀嘀嘀，手机响了起来，是闹钟。闹钟提醒上写着——吃药。</p><p>随后警察 B 又在死者口袋中掏出了一瓶药，药瓶上写着——氯丙嗪。</p><p>……</p><p>氯丙嗪适应症：</p><p>① 治疗精神病：用于控制精神分裂症或其他精神病的兴奋躁动、紧张不安、幻觉、妄想等症状，对忧郁症状及木僵症状的疗效较差。对Ⅱ型精神分裂症患者无效，甚至可加重病情。</p><p>② 镇吐：几乎对各种原因引起的呕吐，如尿毒症、胃肠炎、癌症、妊娠及药物引起的呕吐均有效。也可治疗顽固性呃逆。但对晕动病呕吐无效。</p><p>③ 低温麻醉及人工冬眠：用于低温麻醉时可防止休克发生。人工冬眠时，与哌替啶、异丙嗪配成冬眠合剂用于创伤性休克、中毒性休克、烧伤、高烧及甲状腺危象的辅助治疗。</p><p>④ 与镇痛药合用，治疗癌症晚期患者的剧痛。</p><p>⑤ 治疗心力衰竭。</p><p>⑥ 试用于治疗巨人症。</p></section>
<section><h2>13<a href="#13"><span>#</span></a></h2><p>一段时间后，警察联系到该死者的家属，通知其来认尸。</p><p>录口供时，家属说到——</p><p>“这孩子其实是我十几年前在路边捡到的……”</p><p>“当时他身上浑身都是伤痕……”</p><p>“哪有这么没良心的父母啊把孩子打成这样还要抛弃……”</p></section>]]></content>
    </entry>
</feed>
