<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>算法 on kamuszhou&#39;s blog</title>
    <link>https://ykyi.net/tags/%E7%AE%97%E6%B3%95/</link>
    <description>Recent content in 算法 on kamuszhou&#39;s blog</description>
    <generator>Hugo</generator>
    <language>zh-cn</language>
    <lastBuildDate>Sat, 11 Dec 2021 15:35:42 +0000</lastBuildDate>
    <atom:link href="https://ykyi.net/tags/%E7%AE%97%E6%B3%95/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Fiduccia Mattheyses算法(即FM算法)的论文解读</title>
      <link>https://ykyi.net/?p=1727/</link>
      <pubDate>Sat, 11 Dec 2021 15:35:42 +0000</pubDate>
      <guid>https://ykyi.net/?p=1727/</guid>
      <description>&lt;p&gt;kamuszhou的博客，转载请注明URL。&lt;/p&gt;
&lt;p&gt;现代大规模集成电路图（VLSI）非常庞大，当我们希望用多个FPGA仿真一个VLSI时，需要把VLSI在满足一些约束条件的情况下切割成多个小部分，每个部分都可以装进一个FPGA。&lt;/p&gt;
&lt;p&gt;这个问题抽象成数学模型，实际上就是一个超图分割的问题。在超图分割领域有一篇发表于1982年的论文，名字是”A Linear-Time Heuristic for Improving Network Partitions”。这篇论文提出了一种改进的“超图二分问题”算法，简称为FM算法。虽然在1982年这篇论文发表时，“超图分割”算法领域已经发展了近十年。但这篇论文似乎有着近乎祖师爷级论文的地位，相当多的后期该领域的论文都会引用这篇文章。论文发表之后该领域继续发展出的“层次化超图多分割”算法可以看成是FM算法发展而来。该算法中涉及到的概念和思路是后续算法的基础，是很好的该领域入门学习的资料。&lt;br&gt;
（更多超图及超图分割的基础概念请自行搜索，本博客主要解读论文）&lt;/p&gt;
&lt;p&gt;论文的下载地址：&lt;br&gt;
&lt;a href=&#34;https://ieeexplore.ieee.org/document/1585498&#34; title=&#34;https://ieeexplore.ieee.org/document/1585498&#34;&gt;https://ieeexplore.ieee.org/document/1585498&lt;/a&gt;{.wp-editor-md-post-content-link}&lt;/p&gt;
&lt;p&gt;在论文的摘要部分论述到：本文提出了一种启发式的，利用最小割(mincut)的迭代算法解决超图二分问题。该算法在最坏情况下的时间复杂度也是线性的。在实际应用中，绝大多数情况下，该算法都只需要很少次数的迭代。算法有三个特点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;超图被分成两个Block。每次移动一个结点把它从原来的Block移往另一个Block。同时维持两个Block的平衡。重要的是，这个平衡不是基于每个Block中的结点数量，而是更一般的size of block的概念，它考虑到了每个结点的权重是不一样的。&lt;/li&gt;
&lt;li&gt;利用一个相当高效的数据结构，可以在O(1)常数时间复杂度内找到需要移动的最佳结点。&lt;/li&gt;
&lt;li&gt;在移动了某个结点后，再高效地更新受上次移动影响的结点的信息(即论文后面会提到的结点的gain值)。这第三个特点亦在论文的Introduction中被再次提到，作者认为这是该论文的主要贡献(main contribution).&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;术语及基本概念&#34;&gt;术语及基本概念&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;n(i): 当i是超边的编号时，n(i)定义为每个超边上的结点数目。&lt;/li&gt;
&lt;li&gt;s(i)或p(i): 当i表示结点时，s(i)或p(i)表示结点上的PIN数目，即结点一共跟多个条超边有连接，更多时候亦称为结点的size。&lt;/li&gt;
&lt;li&gt;邻居结点： 如果两个结点至少能通过一条超边连接，即为邻居结点。&lt;/li&gt;
&lt;li&gt;A，B： 代表超图二分割后的两个BLOCK。&lt;/li&gt;
&lt;li&gt;｜A｜： $|A| = \sum_{i=i}^{n}{s(i)}$ 即Block A的size定义为Block A中所有的结点的size的连加。&lt;/li&gt;
&lt;li&gt;A(n)或B(n)： n表示编号为n的边，A(n)则表示该条n在Block A中的结点数。&lt;/li&gt;
&lt;li&gt;cut: 在A和B中都有结点的超边。&lt;/li&gt;
&lt;li&gt;cutstate: 一条超边是不是cut（后来发展成多分割问题中的cutsize）。&lt;/li&gt;
&lt;li&gt;cell gains: 当移动一个结点到另一个BLOCK时，cut减少的数目。&lt;br&gt;
&lt;img decoding=&#34;async&#34; src=&#34;http://supershell.cn/wp-content/uploads/2021/12/cell_gains.png&#34; alt=&#34;cell gains&#34; /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;维持平衡&#34;&gt;维持平衡&lt;/h2&gt;
&lt;p&gt;最容易想到的是就是使超图二分割后的两个BLOCK中的结点数量大致相同。不过，可以稍微变复杂一点，即考虑每个结点的权重。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;W ＝ |A| + |B| 所有结点的size连加和&lt;/li&gt;
&lt;li&gt;r = |A| / (|A| + |B|) 一个大小0到1之间的比率&lt;/li&gt;
&lt;li&gt;smax = $\max_{1&amp;lt;i&amp;lt;n}{s(i)}$ 最大的结点size&lt;br&gt;
* rW – k ＊ smax &amp;lt;= |A| &amp;lt;= rW + k * smax；k &amp;gt; 1 平衡公式&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;公式不难，描述地很清楚。简单地讲，block的size考虑到了每个结点的权重不同。另外，允许每个block的size在满足比率r的附近上下浮动k个最大结点size。它的含义是，在刚好满足分割比率r的时候，还能够至少移动k个结点。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Sicily 1031 Campus 解题报告.</title>
      <link>https://ykyi.net/?p=339/</link>
      <pubDate>Mon, 26 Dec 2011 05:12:28 +0000</pubDate>
      <guid>https://ykyi.net/?p=339/</guid>
      <description>&lt;div&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;div&gt;
    1 原题中文大意;
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    Sicily 1031 Campus实际上就是求一个图中给出两点的最短路径的问题。
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    2 算法思想及解题用到的主要数据结构;
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    用 dijkstra 算法求给定两点的最短路径.
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    按路径长度递增次序产生最短路径算法： 　　把V分成两组： 　　（1）S：已求出最短路径的顶点的集合 　　（2）V-S=T：尚未确定最短路径的顶点集合 　　将T中顶点按最短路径递增的次序加入到S中， 　　保证：（1）从源点V0到S中各顶点的最短路径长度都不大于 　　从V0到T中任何顶点的最短路径长度 　　（2）每个顶点对应一个距离值 　　S中顶点：从V0到此顶点的最短路径长度 　　T中顶点：从V0到此顶点的只包括S中顶点作中间 　　顶点的最短路径长度 　　依据：可以证明V0到T中顶点Vk的最短路径，或是从V0到Vk的 　　直接路径的权值；或是从V0经S中顶点到Vk的路径权值之和。
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    3 &amp;nbsp;逐步求精算法描述
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    用邻接矩阵存放图.1. 初使时令 S={V0},T={其余顶点}，T中顶点对应的距离值 　　若存在&lt;V0,Vi&gt;，d(V0,Vi)为&lt;V0,Vi&gt;弧上的权值 　　若不存在&lt;V0,Vi&gt;，d(V0,Vi)为&amp;prop; 　　2. 从T中选取一个其距离值为最小的顶点W且不在S中，加入S 　　3. 对T中顶点的距离值进行修改：若加进W作中间顶点，从V0到Vi的 　　距离值比不加W的路径要短，则修改此距离值 　　重复上述步骤2、3，直到S中包含所有顶点，即S=T为止
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    3 程序注释清单 // 这份代码通不过sicily。有case错误。我实在找不到原因。
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    &lt;pre class=&#34;brush:cpp&#34;&gt;#include &amp;lt;map&amp;gt;
&lt;p&gt;#include &amp;lt;vector&amp;gt;&lt;/p&gt;
&lt;p&gt;#include &amp;lt;string&amp;gt;&lt;/p&gt;
&lt;p&gt;#include &amp;lt;iostream&amp;gt;&lt;/p&gt;
&lt;p&gt;#include &amp;lt;cstdlib&amp;gt;&lt;/p&gt;
&lt;p&gt;#include &amp;lt;cstdio&amp;gt;&lt;/p&gt;
&lt;p&gt;#include &amp;lt;cstring&amp;gt;&lt;/p&gt;
&lt;p&gt;#include &amp;lt;cassert&amp;gt;&lt;/p&gt;
&lt;p&gt;#define INFINITE 0x0FFFFFFF&lt;/p&gt;
&lt;p&gt;// 这个类的函数几乎不做参数有效性的检查.&lt;/p&gt;
&lt;p&gt;class graph_t&lt;/p&gt;</description>
    </item>
    <item>
      <title>sicily 2014. Dairy Queen 解题报告</title>
      <link>https://ykyi.net/?p=310/</link>
      <pubDate>Sat, 17 Dec 2011 12:05:10 +0000</pubDate>
      <guid>https://ykyi.net/?p=310/</guid>
      <description>&lt;div&gt;
  &lt;p&gt;
    Sun Yat-sen University ACM 2014. Dairy Queen
  &lt;/p&gt;
  &lt;p&gt;
    1.&amp;nbsp;原题中文大意&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;;&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    给出一个在&amp;nbsp;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;[1,&amp;nbsp;300]&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;之间的数字&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;N&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;。然后给出一个集合，这个集合中有&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;C&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;个数字，&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;C&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;在&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;[1,&amp;nbsp;8]&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;之间。该集合中的每个数字在&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;[1,&amp;nbsp;200]&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;之间。问如何用这个集合中的数字组合（数字可以重复使用），使它们的总和等于&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;N&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;。&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    2.&amp;nbsp;&lt;span style=&#34;font-family: 宋体;&#34;&gt;解这种题毫不犹豫地想到用动态规划。&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    3.&amp;nbsp;&lt;span style=&#34;font-family: 宋体;&#34;&gt;设一个数组&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;ways[301];&amp;nbsp;ways[n]&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;表示有多少种方法可以组合成和&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;n&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;。假设集合中只一个数字&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;x&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;。那么问题就非常简单，只能取&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;n&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;个该数字，和的集合为&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;{x,&amp;nbsp;2x,&amp;nbsp;3x}&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;，即&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;ways[x]=1&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;，&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;ways[2x]=1,&amp;nbsp;ways[3x]=1&amp;nbsp;&amp;#8230;.&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;。如果集合中有&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;m&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;数字，假设我们已经求得了用这&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;m&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;个数字的组合可以得到的和的数目存到了&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;ways&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;数组里。即对于&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;m&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;个数字，已求得&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;ways[1]&amp;nbsp;=&amp;nbsp;?,&amp;nbsp;ways[2]&amp;nbsp;=&amp;nbsp;?,&amp;nbsp;ways[3]&amp;nbsp;=&amp;nbsp;?&amp;nbsp;&amp;#8230;..&amp;nbsp;Ways[300]&amp;nbsp;=&amp;nbsp;?&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;。&amp;nbsp;那么在此基础上，再加多一个数字，即&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;m+1&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;个数字的情况会是如何呢。设新加入的这个数字的值是&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;p&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;，则应该是&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;ways[q]&amp;nbsp;+=&amp;nbsp;ways[q-p]&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;。（&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;q&amp;nbsp;&gt;&amp;nbsp;p&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;）&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    4.&amp;nbsp;程序注释清单.
  &lt;/p&gt;
  &lt;pre class=&#34;brush:cpp&#34;&gt;#include &amp;lt;string.h&amp;gt;

#include &amp;lt;stdlib.h&amp;gt;

#include &amp;lt;stdio.h&amp;gt;



int main(int argc, char* argv[])

{

int N, C, coin;  // N为题意中的N，C即题意中的C. coin作临时变量用，不解释，可见下面的代码。

int ways[301] = { 0 };  // 见第三部分的分析。

ways[0] = 1;  // 没有实际意义。为了方便计算.



scanf(&#34;%d %d&#34;, &amp;N, &amp;C);

for ( int i = 0; i &amp;lt; C; i++)

{

scanf(&#34;%d&#34;, &amp;coin);

for ( int j = coin; j &amp;lt;= N; j++ )

{

ways[j] += ways[j-coin];  // 见第3部分的分析.

}

}

printf(&#34;%d\n&#34;, ways[N]);



return 0;

}&lt;/pre&gt;
&lt;p&gt;
  &amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
  5.时间复杂度，空间复杂度分析。
&lt;/p&gt;
&lt;p&gt;
  空间复杂度是确定的常数。时间复杂度是&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;o(n).&amp;nbsp;n&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;为有多少种面值的硬币。&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
  &lt;a href=&#34;http://ykyi.net&#34;&gt;http://ykyi.net&lt;/a&gt; zausiu&#39;s blog
&lt;/p&gt;
&lt;p&gt;
  原题：
&lt;/p&gt;
&lt;h1&gt;
  Description
&lt;/h1&gt;
&lt;p&gt;
  Bessie, always in need of an income, has decided to leverage her dairy skills by taking a part-time job at the local Dairy Queen restaurant. She is running a special cash register (since she has hooves instead of fingers and thus requires special accommodation). Her job is making change for customers as they make a purchase.
&lt;/p&gt;
&lt;p&gt;
  As she was counting out 83 cents in change, she wondered: &#34;How many ways can I count out 83 cents? I can use three quarters and eight pennies, seven dimes and three pennies, 83 pennies&amp;#8230; there must be a zillion ways!&#34;
&lt;/p&gt;
&lt;p&gt;
  How many different ways can one make change for N (1 &amp;le; N &amp;le; 300) cents using coins from a set of C (1 &amp;le; C &amp;le; 8) coins of supplied values C_i (1 &amp;le; C_i &amp;le; 200)? &#34;Different&#34; means differing counts of coins.
&lt;/p&gt;
&lt;p&gt;
  Thus, 8 cents can be made, in American currency, with 1 five-cent piece + 3 one-cent pieces and also with 8 one-cent pieces. Using 3 one-cent pieces + 1 five-cent piece is the same as 1 five-cent piece + 3 one-cent pieces, so one can create eight cents in just two different ways. Note that some coin systems are poor at making change and result in an answer of &#39;0&#39;.
&lt;/p&gt;
&lt;p&gt;
  Coin values in the input file are listed in descending order from largest to smallest. All coin values will be distinct.
&lt;/p&gt;
&lt;h1&gt;
  Input
&lt;/h1&gt;
&lt;p&gt;
  &amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
  Line 1: Two space-separated integers: N and C&lt;br /&gt; Lines 2..C+1: Line i+1 contains a single integer: C_i
&lt;/p&gt;
&lt;p&gt;
  &amp;nbsp;
&lt;/p&gt;
&lt;h1&gt;
  Output
&lt;/h1&gt;
&lt;p&gt;
  Line 1: A single line with a single integer that is the number of ways to create N cents of change using the supplied coins. The answer is guaranteed to fit into a signed 32-bit int
&lt;/p&gt;
&lt;p&gt;
  &amp;nbsp;
&lt;/p&gt;
&lt;h1&gt;
  Sample Input
&lt;/h1&gt;
&lt;pre&gt;83 5
50
25
10
5
1&lt;/pre&gt;
&lt;h1&gt;
  Sample Output
&lt;/h1&gt;
&lt;pre&gt;159&lt;/pre&gt;
&lt;p&gt;
  &amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
  copyright ykyi.net
&lt;/p&gt;
&lt;/div&gt;</description>
    </item>
    <item>
      <title>中大sicily 1426. Phone List 解题报告</title>
      <link>https://ykyi.net/?p=280/</link>
      <pubDate>Sun, 11 Dec 2011 15:50:04 +0000</pubDate>
      <guid>https://ykyi.net/?p=280/</guid>
      <description>&lt;div&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;div&gt;
    1.原题中文大意;
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    给出一组数字，最多一万个，判断这组数字中是否存在一个数字是其它一个数字的前缀。
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    2.算法思想及解题用到的主要数据结构;
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    每读入一个数字字符串，则把该数字串从高位到低位分解成一个个数字字符。然后开始以最高位数字为树的根，第二个数字为根的子孙结点，第三个数字为第二个数字的子孙结点。如果碰到最后一个数字，如果这组数字符合要求的话则最后一个数字字符一定是叶子结点。不断的加入新的数字字符串到树中，如果在加入的过程中使以前的叶子结点变成了非叶子结点，或者新加入的数字字符串的最后一个数字在树中不是一个叶子结点，则报告这组数字字符串不符合要求。反之，则符合要求。
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    3.逐步求精算法描述（含过程及变量说明）;
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    每个结点记下关键信息,一个数字字符。再加上一个指向其它信息的指针. 这个指针指向一个node_data_t结构。结构体中放置了一个tag标签，记字是不是一个数字字符串的最后一个数字；以及一个指向STL的set容器，容器中放置了所有子孙结点。如下代码描述。
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    struct node_t
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    {
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    char _ch;
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    node_data_t* _data;
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    };
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    struct node_data_t
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    {
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    set&lt;node_t, node_comp&gt; &amp;nbsp;_nodes;
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    bool _terminal;
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    };
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    剩下的逻辑便是分析数字字符串，把每个字符拆出加入树中。
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    4.程序注释清单
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    &lt;pre class=&#34;brush:cpp&#34;&gt;#include &amp;lt;set&amp;gt;
&lt;p&gt;#include &amp;lt;algorithm&amp;gt;&lt;/p&gt;
&lt;p&gt;#include &amp;lt;cstring&amp;gt;&lt;/p&gt;
&lt;p&gt;#include &amp;lt;cstdlib&amp;gt;&lt;/p&gt;
&lt;p&gt;#include &amp;lt;cstdio&amp;gt;&lt;/p&gt;
&lt;p&gt;using namespace std;&lt;/p&gt;
&lt;p&gt;struct node_comp;&lt;/p&gt;
&lt;p&gt;struct node_data_t;&lt;/p&gt;
&lt;p&gt;struct node_t&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;char _ch;&lt;/p&gt;
&lt;p&gt;node_data_t* _data;&lt;/p&gt;
&lt;p&gt;};&lt;/p&gt;
&lt;p&gt;struct node_comp  // 给STL的set容器的排序算子。&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;bool operator()(const node_t&amp;amp; left, const node_t&amp;amp; right)const&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;return left._ch &amp;lt; right._ch;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;};
&lt;a href=&#34;http://ykyi.net&#34;&gt;http://ykyi.net&lt;/a&gt; zausiu&#39;s blog
struct node_data_t&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;set&amp;lt;node_t, node_comp&amp;gt;  _nodes;&lt;/p&gt;
&lt;p&gt;bool _terminal;  // 标记是不是一个电话号码的终点字符了。&lt;/p&gt;
&lt;p&gt;};&lt;/p&gt;
&lt;p&gt;typedef set&amp;lt;node_t, node_comp&amp;gt; nodes_set;&lt;/p&gt;
&lt;p&gt;nodes_set top_nodes;&lt;/p&gt;
&lt;p&gt;// 如果已经可以判断电话号码不满足要求就返回false.&lt;/p&gt;
&lt;p&gt;// 递归调用该函数。&lt;/p&gt;
&lt;p&gt;bool odyssey(nodes_set&amp;amp; nodes, const char* num)&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;if ( 0 == *num )&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;return true;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;//&lt;/p&gt;
&lt;p&gt;node_t node;&lt;/p&gt;
&lt;p&gt;node._ch = *num;&lt;/p&gt;
&lt;p&gt;node._data = new node_data_t;&lt;/p&gt;
&lt;p&gt;node._data-&amp;gt;_terminal = !num[1];&lt;/p&gt;
&lt;p&gt;pair&amp;lt;nodes_set::iterator, bool&amp;gt; retval = nodes.insert(node);&lt;/p&gt;
&lt;p&gt;if ( retval.second )  // 还没有这个数字的结点.新插入的.&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;bool b;&lt;/p&gt;
&lt;p&gt;b = odyssey(retval.first-&amp;gt;_data-&amp;gt;_nodes, num+1);&lt;/p&gt;
&lt;p&gt;return b;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;else  // 已经存在&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;delete node._data;&lt;/p&gt;
&lt;p&gt;// 并且已经是之前一个数字串的最后一个数字字符.或者现在这个字符是最后一个.&lt;/p&gt;
&lt;p&gt;if ( retval.first-&amp;gt;_data-&amp;gt;_terminal || !num[1] )&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;return false;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;else if ( !num[1] )&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;retval.first-&amp;gt;_data-&amp;gt;_terminal = true;&lt;/p&gt;
&lt;p&gt;return true;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;else&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;retval.first-&amp;gt;_data-&amp;gt;_terminal = false;&lt;/p&gt;
&lt;p&gt;bool b;&lt;/p&gt;
&lt;p&gt;b = odyssey(retval.first-&amp;gt;_data-&amp;gt;_nodes, num+1); // 递归&lt;/p&gt;
&lt;p&gt;return b;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;// 释放内存.&lt;/p&gt;
&lt;p&gt;void free_mem(nodes_set&amp;amp; nodes)&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;for ( nodes_set::const_iterator ite = nodes.begin();&lt;/p&gt;
&lt;p&gt;ite != nodes.end();&lt;/p&gt;
&lt;p&gt;++ite )&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;free_mem(ite-&amp;gt;_data-&amp;gt;_nodes);&lt;/p&gt;
&lt;p&gt;delete ite-&amp;gt;_data;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;nodes.clear();&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;int main(int argc, char* argv[])&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;int case_count;   // 有多少个case&lt;/p&gt;
&lt;p&gt;int phone_num_count;    // 多少个电话霖巴&lt;/p&gt;
&lt;p&gt;char phone_num_str[11];   // 存电话霖巴&lt;/p&gt;
&lt;p&gt;bool successed;  // 一组数字字符串是否符合要求&lt;/p&gt;
&lt;p&gt;scanf(&amp;quot;%d&amp;quot;, &amp;amp;case_count);&lt;/p&gt;
&lt;p&gt;for ( int i = 0; i &amp;lt; case_count; i++ )&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;scanf(&amp;quot;%d&amp;quot;, &amp;amp;phone_num_count);&lt;/p&gt;
&lt;p&gt;successed = true;&lt;/p&gt;
&lt;p&gt;for ( int j = 0; j &amp;lt; phone_num_count; j++ )&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;scanf(&amp;quot;%s&amp;quot;, phone_num_str);&lt;/p&gt;
&lt;p&gt;if ( successed )&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;successed = odyssey(top_nodes, phone_num_str);&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;if ( successed )&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;printf(&amp;ldquo;YES\n&amp;rdquo;);&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;else&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;printf(&amp;ldquo;NO\n&amp;rdquo;);&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;free_mem(top_nodes);&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;return 0;&lt;/p&gt;
&lt;p&gt;}
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;
  &amp;nbsp;
&lt;/p&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  5.测试数据
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  用简单的脚本帮助生成测试数据.
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  #!/bin/bash
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  INDEX=0
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  if [ -e $1 ];then
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  COUNT=200
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  else
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  COUNT=$1
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  fi
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  while [ $INDEX -lt $COUNT ];do
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  let &#34;INDEX=$INDEX+1&#34;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  echo $RANDOM
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  done
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  6.对时间复杂度，空间复杂度方面的分析.
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  本算法的时间复杂度的空间复杂度一般都介于O(logN)和O(N)之间。
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  //////////////// 原题 &amp;nbsp;//////////////
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  1426. Phone List
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  Description
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  Given a list of phone numbers, determine if it is consistent in the sense that no number is the pre?x of another. Let&amp;rsquo;s say the phone catalogue listed these numbers:
&lt;/div&gt;
&lt;div&gt;
  ? Emergency 911
&lt;/div&gt;
&lt;div&gt;
  ? Alice 97 625 999
&lt;/div&gt;
&lt;div&gt;
  ? Bob 91 12 54 26
&lt;/div&gt;
&lt;div&gt;
  In this case, it&amp;rsquo;s not possible to call Bob, because the central would direct your call to the emergency line as soon as you had dialled the ?rst three digits of Bob&amp;rsquo;s phone number. So this list would not be consistent.
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  Input
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  The ?rst line of input gives a single integer, 1 &amp;le; t &amp;le; 40, the number of test cases. Each test case starts with n, the number of phone numbers, on a separate line, 1 &amp;le; n &amp;le; 10000. Then follows n lines with one unique phone number on each line. A phone number is a sequence of at most ten digits.
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  Output
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  For each test case, output &amp;ldquo;YES&amp;rdquo; if the list is consistent, or &amp;ldquo;NO&amp;rdquo; otherwise.
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  Sample Input
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  2
&lt;/div&gt;
&lt;div&gt;
  3
&lt;/div&gt;
&lt;div&gt;
  911
&lt;/div&gt;
&lt;div&gt;
  97625999
&lt;/div&gt;
&lt;div&gt;
  91125426
&lt;/div&gt;
&lt;div&gt;
  5
&lt;/div&gt;
&lt;div&gt;
  113
&lt;/div&gt;
&lt;div&gt;
  12340
&lt;/div&gt;
&lt;div&gt;
  123440
&lt;/div&gt;
&lt;div&gt;
  12345
&lt;/div&gt;
&lt;div&gt;
  98346
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  Sample Output
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  NO
&lt;/div&gt;
&lt;div&gt;
  YES
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;/div&gt;</description>
    </item>
    <item>
      <title>sicily 1022 Poor contestant Prob 解题报告。</title>
      <link>https://ykyi.net/?p=256/</link>
      <pubDate>Mon, 05 Dec 2011 13:27:27 +0000</pubDate>
      <guid>https://ykyi.net/?p=256/</guid>
      <description>&lt;div&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;div&gt;
    &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;解 &amp;nbsp;题 &amp;nbsp;报 &amp;nbsp;告
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    1 1022 Poor contestant Prob原题中文大意;
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    对于大约十万条数据：如果共奇数条数据则找到最中间那条记录。如果有偶数条记录则忽略。
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    2 算法思想及解题用到的主要数据结构;
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    因为数据的规模比较大。如果给十万条记录排序的话显然会超时。考虑到题目只需要找到最中间那条。易想到把数据平分成两部分，第一部分的数据全部大于第二部分的数据。创建两个堆结构。第一部分的较大数据建大小顶堆，第二部分的较小数据建成大顶堆。在插入数据的过程中，动态维护这两个堆，使小顶堆的元素数等于大顶堆的元素数或者小顶堆的元素比大顶堆的元素多一。本题用性线表来存储堆。
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    3 详细解题思路;
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    因为最终需要输出一个字符串。为了节省拷贝字符串的开销，把字符串存到一个字符串池中，而每个堆中的元素只维护这个字符串池的索引号。
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    初始时，小顶堆和大顶堆的大小都是0。
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    1. 当输入第一条数据时，把这条数据放入小顶堆中。
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    2. 当输入更多数据时：
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    2.1 如果小顶堆和大顶堆的元素个数一样多。为保证添加新数据后，我们需要的最中间的数据在小顶堆的上部。又分两种情况处理：
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    2.1.1 如果待加入数据大于或等于大顶堆的堆顶元素。则把这个待加入数据加入小顶堆。调整小顶堆.
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    2.1.2 如果待加入数据小于大顶堆的堆顶元素.则把大顶堆的堆顶元素弹出添加到小顶堆，调整这两个堆。之后，把待加入数据加入大顶堆。
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    2.2 如果小顶堆和大顶堆的元素个数不一样多。因为前面的约定，那么必定是小顶堆的元素个数比大顶堆的元素个数多一个。仍然分两种情况：
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    2.2.1 如果待加入数据大于小顶堆的堆顶元素。则把待加入数据加入小顶堆并调整，调整后把小顶堆的堆顶弹出加入大顶堆并调整。小顶堆在弹出堆顶元素后再调整一次。
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    2.2.1 如果待加入数据不大于小顶堆的堆顶元素。则把该数据加入大顶堆，调整大顶堆。
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    输入结束时直接取小顶堆的堆顶元素即要求的解。根据元素中的字符串索引可以拿到需要打印的字符串，本题中即那位poor contestant。
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    4 逐步求精算法描述（含过程及变量说明）;
  &lt;/div&gt;
  &lt;div&gt;
    &lt;pre class=&#34;brush:cpp&#34;&gt;int g_name_pool_index = 0;   // 名字池的当前索引号.
&lt;p&gt;char g_name_pool[100001][11];  // 用来存名字的字符串池.&lt;/p&gt;
&lt;p&gt;下面是堆相关的描述。&lt;/p&gt;
&lt;p&gt;struct heap_elem_t&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;// string _name;&lt;/p&gt;
&lt;p&gt;int _name_index;  // 名字的索引&lt;/p&gt;
&lt;p&gt;int _solved_count;  // 原题意中表示解决了多少个问题.用这个数量比较堆元素的大小。&lt;/p&gt;
&lt;p&gt;};&lt;/p&gt;
&lt;p&gt;// STL 用的堆算法的比较算子.&lt;/p&gt;
&lt;p&gt;struct heap_elem_less_comparator&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;bool operator()(const heap_elem_t&amp;amp; left,  const heap_elem_t&amp;amp; right)&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;return left._solved_count &amp;lt; right._solved_count;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;};&lt;/p&gt;
&lt;p&gt;// STL 用的堆算法的比较算子.&lt;/p&gt;
&lt;p&gt;struct heap_elem_larger_comparator&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;bool operator()(const heap_elem_t&amp;amp; left,  const heap_elem_t&amp;amp; right)&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;return left._solved_count &amp;gt; right._solved_count;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;};&lt;/p&gt;
&lt;p&gt;heap_elem_less_comparator less_comp;&lt;/p&gt;
&lt;p&gt;heap_elem_larger_comparator larger_comp;&lt;/p&gt;
&lt;p&gt;// 从下往而上调整堆。用到了STL的堆调整算法。堆元素存在线性表中，但不用第一个元素。因为之前的版本用自己写的堆调整算法为了计算坐标方便就不用第一个元素。&lt;/p&gt;
&lt;p&gt;inline void adjust_heap_up(heap_elem_t heap[], int tail_pos, bool inc)&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;if ( inc )&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;push_heap(heap+1, heap+tail_pos+1, larger_comp);&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;else&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;push_heap(heap+1, heap+tail_pos+1, less_comp);&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;// 把堆顶元素弹出.并调整余下的元素仍然是一个堆。也用了STL的算法.&lt;/p&gt;
&lt;p&gt;inline void popup_the_top(heap_elem_t heap[], int tail_pos, bool inc)&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;if ( inc )&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;pop_heap(heap+1, heap+tail_pos+1, larger_comp);&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;else&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;pop_heap(heap+1, heap+tail_pos+1, less_comp);&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;// 下面是自已写的堆调整算法。有从上而下的调整，也有从下而上的调整。&lt;/p&gt;
&lt;p&gt;/** 调整堆.从下往下调整.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;@param heap 堆的首地址.用顺序表存放堆.但不用下标为0的元素.这个元素可用来作临时存储.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;@param summit_pos 堆顶的位置.summit_pos &amp;gt; 0&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;@param tail_pos 最后一个元素的位置.tail_pos &amp;gt; 0&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;@param inc 是否建小顶堆.如果false则大顶堆.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*/&lt;/p&gt;
&lt;p&gt;void adjust_heap_top2bottom(heap_elem_t heap[], int summit_pos, int tail_pos, bool inc)&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;int i;&lt;/p&gt;
&lt;p&gt;heap[0] = heap[summit_pos];  // 存下堆顶的元素先.&lt;/p&gt;
&lt;p&gt;for ( i = 2 * summit_pos; i &amp;lt;= tail_pos; i *= 2 )&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;if ( inc )  // 调整小顶堆&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;if ( i &amp;lt; tail_pos &amp;amp;&amp;amp; heap[i]._solved_count &amp;gt; heap[i+1]._solved_count )&lt;/p&gt;
&lt;p&gt;i++;&lt;/p&gt;
&lt;p&gt;if ( ! (heap[0]._solved_count &amp;gt; heap[i]._solved_count) )&lt;/p&gt;
&lt;p&gt;break;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;else  // 调整大顶堆&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;if ( i &amp;lt; tail_pos &amp;amp;&amp;amp; heap[i]._solved_count &amp;lt; heap[i+1]._solved_count )&lt;/p&gt;
&lt;p&gt;i++;&lt;/p&gt;
&lt;p&gt;if ( ! (heap[0]._solved_count &amp;lt; heap[i]._solved_count) )&lt;/p&gt;
&lt;p&gt;break;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;heap[summit_pos] = heap[i];&lt;/p&gt;
&lt;p&gt;summit_pos = i;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;heap[summit_pos] = heap[0];&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;/** 调整堆.从下往上调整.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;@param heap 堆的首地址.用顺序表存放堆.但不用下标为0的元素.这个元素可用来作临时存储.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;@param tail_pos 最后一个元素的位置.tail_pos &amp;gt; 0&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;@param inc 是否建小顶堆.如果false则大顶堆.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*/&lt;/p&gt;
&lt;p&gt;void adjust_heap_bottom2top(heap_elem_t heap[], int tail_pos, bool inc)&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;int i;&lt;/p&gt;
&lt;p&gt;heap[0] = heap[tail_pos];&lt;/p&gt;
&lt;p&gt;for ( i = tail_pos; i &amp;gt; 1; i /= 2 )&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;int parent_pos = i / 2;&lt;/p&gt;
&lt;p&gt;if ( inc )  // 调整小顶堆&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;if ( heap[parent_pos]._solved_count &amp;gt; heap[0]._solved_count )&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;heap[i] = heap[parent_pos];&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;else&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;break;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;else  // 调整大顶堆&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;if ( heap[parent_pos]._solved_count &amp;lt; heap[0]._solved_count )&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;heap[i] = heap[parent_pos];&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;else&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;break;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;heap[i] = heap[0];&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;5 程序注释清单（重要过程的说明）;&lt;/p&gt;
&lt;p&gt;// poor_guy.cpp : Defines the entry point for the console application.
//&lt;/p&gt;
&lt;p&gt;#include &amp;lt;algorithm&amp;gt;
#include &amp;lt;string&amp;gt;
#include &amp;lt;vector&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;&lt;/p&gt;
&lt;p&gt;using namespace std;&lt;/p&gt;
&lt;p&gt;template&amp;lt;typename T&amp;gt; class my_vector
{
public:
my_vector(T* addr)
{
m_ary = addr;
m_ava_idx = 0;
}
~my_vector()
{
//  delete []m_ary;
}&lt;/p&gt;
&lt;p&gt;T&amp;amp; operator[](int index)
{
return m_ary[index];
}&lt;/p&gt;
&lt;p&gt;void push_back(const T&amp;amp; v)
{
m_ary[m_ava_idx++] = v;
}&lt;/p&gt;
&lt;p&gt;void resize(int size)
{
m_ava_idx = size;
}&lt;/p&gt;
&lt;p&gt;void shrink(int dec)
{
m_ava_idx -= dec;
}&lt;/p&gt;
&lt;p&gt;int size()
{
return m_ava_idx;
}
private:
T*   m_ary;
int  m_ava_idx;
};&lt;/p&gt;
&lt;p&gt;// 堆的结点定义
int g_name_pool_index = 0;
char g_name_pool[100001][11];&lt;/p&gt;
&lt;p&gt;struct heap_elem_t
{
// string _name;
int _name_index;
int _solved_count;
};&lt;/p&gt;
&lt;p&gt;heap_elem_t g_heap_elems0[50002];
heap_elem_t g_heap_elems1[50002];&lt;/p&gt;
&lt;p&gt;struct heap_elem_less_comparator
{
bool operator()(const heap_elem_t&amp;amp; left,  const heap_elem_t&amp;amp; right)
{
return left._solved_count &amp;lt; right._solved_count;
}
};&lt;/p&gt;
&lt;p&gt;struct heap_elem_larger_comparator
{
bool operator()(const heap_elem_t&amp;amp; left,  const heap_elem_t&amp;amp; right)
{
return left._solved_count &amp;gt; right._solved_count;
}
};&lt;/p&gt;
&lt;p&gt;heap_elem_less_comparator less_comp;
heap_elem_larger_comparator larger_comp;&lt;/p&gt;
&lt;p&gt;/&lt;em&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;em&gt;/
/&lt;/em&gt; inc 为真时调整为小顶堆，为false时调整为大顶堆。                      &lt;em&gt;/
/&lt;/em&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/em&gt;/
inline void adjust_heap_up(heap_elem_t heap[], int tail_pos, bool inc)
{
if ( inc )
{
push_heap(heap+1, heap+tail_pos+1, larger_comp);
}
else
{
push_heap(heap+1, heap+tail_pos+1, less_comp);
}
}&lt;/p&gt;
&lt;p&gt;inline void popup_the_top(heap_elem_t heap[], int tail_pos, bool inc)
{
if ( inc )
{
pop_heap(heap+1, heap+tail_pos+1, larger_comp);
}
else
{
pop_heap(heap+1, heap+tail_pos+1, less_comp);
}
}&lt;/p&gt;
&lt;p&gt;int main(int argc, char* argv[])
{
const int BUFF_LEN = 64;
char buff[BUFF_LEN];
int case_count;  // 记有多少个case;
int contestant_count;
my_vector&amp;lt;heap_elem_t&amp;gt; littletop_heap(g_heap_elems0);
my_vector&amp;lt;heap_elem_t&amp;gt; bigtop_heap(g_heap_elems1);
heap_elem_t contestant;
string name;
// vector&amp;lt;string&amp;gt; output_vec;&lt;/p&gt;
&lt;p&gt;scanf(&amp;quot;%d&amp;quot;, &amp;amp;case_count);
for ( int i = 0; i &amp;lt; case_count; i++ )
{
littletop_heap.resize(1);  // 为了方便计算.下标0的位置不存堆的元素.
bigtop_heap.resize(1);
g_name_pool_index = 0;
contestant_count = 0;&lt;/p&gt;
&lt;p&gt;while(true)
{
scanf(&amp;quot;%s&amp;quot;, buff);&lt;/p&gt;
&lt;p&gt;int little_heap_count = littletop_heap.size() - 1;
int big_heap_count = bigtop_heap.size() - 1;&lt;/p&gt;
&lt;p&gt;if ( buff[0] == &#39;Q&#39; )  // 查询. Querry
{
if ( little_heap_count == big_heap_count || 0 == contestant_count )
{
printf(&amp;ldquo;No one!\n&amp;rdquo;);
//output_vec.push_back(&amp;ldquo;No one!\n&amp;rdquo;);
}
else
{
printf(&amp;quot;%s\n&amp;quot;, g_name_pool[littletop_heap[1]._name_index]);
//output_vec.push_back(g_name_pool[littletop_heap[1]._name_index]);
//output_vec.push_back(&amp;quot;\n&amp;quot;);
}
}
else if ( buff[0] == &#39;E&#39; )  // 结束.
{
if ( little_heap_count == big_heap_count || 0 == contestant_count )
{
printf(&amp;ldquo;Happy BG meeting!!\n&amp;rdquo;);
//output_vec.push_back(&amp;ldquo;Happy BG meeting!!\n&amp;rdquo;);
}
else
{
printf(&amp;quot;%s%s&amp;quot;,g_name_pool[littletop_heap[1]._name_index], &amp;quot; is so poor.\n&amp;quot;);
//output_vec.push_back(g_name_pool[littletop_heap[1]._name_index]);
//output_vec.push_back(&amp;quot; is so poor.\n&amp;quot;);
}&lt;/p&gt;
&lt;p&gt;break;
}
else if( buff[0] == &#39;A&#39; )// 加入参赛者数据.
{
contestant_count ++;&lt;/p&gt;
&lt;p&gt;scanf(&amp;quot;%s&amp;quot;, g_name_pool[g_name_pool_index]);
contestant._name_index = g_name_pool_index;
g_name_pool_index++;
scanf(&amp;quot;%d&amp;quot;, &amp;amp;contestant._solved_count);&lt;/p&gt;
&lt;p&gt;if ( 1 == contestant_count )  // 第一个参赛者数据.
{
littletop_heap.push_back(contestant);
}
else if ( little_heap_count == big_heap_count )  // 两个堆的元素相等.
{
// 新元素大于大顶堆的堆顶元素，所以插入小顶堆.
if ( contestant._solved_count &amp;gt;= bigtop_heap[1]._solved_count )
{
littletop_heap.push_back(contestant);
adjust_heap_up(&amp;amp;littletop_heap[0], littletop_heap.size()-1, true);
}
else
{
heap_elem_t top = bigtop_heap[1];
popup_the_top(&amp;amp;bigtop_heap[0], bigtop_heap.size()-1, false);
bigtop_heap.shrink(1);&lt;/p&gt;
&lt;p&gt;bigtop_heap.push_back(contestant);
adjust_heap_up(&amp;amp;bigtop_heap[0], bigtop_heap.size()-1, false);&lt;/p&gt;
&lt;p&gt;littletop_heap.push_back(top);
adjust_heap_up(&amp;amp;littletop_heap[0], littletop_heap.size()-1, true);
}
}
else  // 不等.只可能是小顶堆比大顶堆多1.
{
if ( contestant._solved_count &amp;gt; littletop_heap[1]._solved_count )
{
littletop_heap.push_back(contestant);
adjust_heap_up(&amp;amp;littletop_heap[0], littletop_heap.size()-1, true);&lt;/p&gt;
&lt;p&gt;heap_elem_t top = littletop_heap[1];
popup_the_top(&amp;amp;littletop_heap[0], littletop_heap.size()-1, true);
littletop_heap.shrink(1);&lt;/p&gt;
&lt;p&gt;bigtop_heap.push_back(top);
adjust_heap_up(&amp;amp;bigtop_heap[0], bigtop_heap.size()-1, false);
}
else
{
bigtop_heap.push_back(contestant);
adjust_heap_up(&amp;amp;bigtop_heap[0], bigtop_heap.size()-1, false);
}
}
}
}&lt;/p&gt;
&lt;p&gt;if ( i + 1 &amp;lt; case_count )
{
printf(&amp;quot;\n&amp;quot;);
//output_vec.push_back(&amp;quot;\n&amp;quot;);
}
}&lt;/p&gt;
&lt;p&gt;//for ( int i = 0; i &amp;lt; output_vec.size(); i++ )
//{
// cout &amp;lt;&amp;lt; output_vec[i];
//}&lt;/p&gt;
&lt;p&gt;return 0;
}
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;
  &amp;nbsp;
&lt;/p&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  //////// 上面的代码在中山大学ACM网站 www.soj.me 上通过.目前的成绩是第14名.
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  Rank &amp;nbsp;14 &amp;nbsp; &amp;nbsp;2011-12-07 10:00:19 &amp;nbsp; &amp;nbsp;0.18 sec &amp;nbsp; &amp;nbsp;2160 KB &amp;nbsp; &amp;nbsp;6971 Bytes &amp;nbsp; &amp;nbsp; C++ &amp;nbsp; zausiu
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  注意上面的代码绝不能用C++的标准IO cin cout 做输入输出.如果用C++的IO流会造成超时。我为了调这个超时问题调了整整一天！死活想不到是因为C++ IO的问题.童鞋，一定要用 scanf 和 printf 啊。面对十万级的IO，尤其是在做ACM题，cin cout 是魔鬼。
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  原因是：
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  More should be noted about I/O operations in C++. Due to their complex underlying implementation &amp;nbsp;models, cin and cout are comparatively slower than scanf and printf. The difference in performance is shown by many experiences to be more significant if the program is compiled by G++. Therefore if a problem has huge input, using cin and cout will possibly lead to Time Limit Exceed.
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  6 测试数据;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  用一个简单的BASH脚本来创建测试用例。
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &lt;pre class=&#34;brush:other&#34;&gt;#! /bin/bash
&lt;p&gt;INDEX=1&lt;/p&gt;
&lt;p&gt;SHRESHOLD=100000   // 建十万条数据.&lt;/p&gt;
&lt;p&gt;while [ $INDEX -lt $SHRESHOLD ]&lt;/p&gt;
&lt;p&gt;do&lt;/p&gt;
&lt;p&gt;echo &amp;ldquo;ADD name$INDEX $RANDOM&amp;rdquo;&lt;/p&gt;
&lt;p&gt;let &amp;ldquo;INDEX=$INDEX+1&amp;rdquo;&lt;/p&gt;
&lt;p&gt;done&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;
  &amp;nbsp;
&lt;/p&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  7 对时间复杂度，空间复杂度方面的分析.
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  时间复杂度是O(log n), 空间复杂度是 O(n).
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  附原题：
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  1022. Poor contestant Prob
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  Description
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  As everybody known, &amp;ldquo;BG meeting&amp;rdquo; is very very popular in the ACM training team of ZSU.
&lt;/div&gt;
&lt;div&gt;
  After each online contest, they will go out for &amp;ldquo;smoking&amp;rdquo;. Who will be the poor ones that have to BG the others? Of course, the half who solve less problems.
&lt;/div&gt;
&lt;div&gt;
  The rule runs well when the number of the contestants is even. But if the number is odd, it is impossible to divide them into two equal parts. It gives a dilemma to the BG meeting committee. After a careful discussion with Mr. Guo, a new rule emerged: if the number of the contestant is odd, the committee will first sort the contestants according to the number of problems they solved, and then they will pick out the middle one. This poor boy or girl will have no chance to attend the BG meeting.
&lt;/div&gt;
&lt;div&gt;
  Strange rule, isn`t it?
&lt;/div&gt;
&lt;div&gt;
  As the number of the contestants is becoming more and more large, the committee need to write a program which will pick out the poor one efficiently.
&lt;/div&gt;
&lt;div&gt;
  Note that: Every contestant solves different number of problems. The total number of the contestants will not exceed 10^5.
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  Input
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  There are several cases in the input. The first line of the input will be an integer M, the number of the cases.
&lt;/div&gt;
&lt;div&gt;
  Each case is consisted of a list of commands. There are 3 types of commands.
&lt;/div&gt;
&lt;div&gt;
  1. Add xxx n : add a record to the data base, where xxx is the name of the contestant, which is only consisted of at most 10 letters or digits, n is the number of problems he/she solved. (Each name will appear in Add commands only once).
&lt;/div&gt;
&lt;div&gt;
  2.Query :
&lt;/div&gt;
&lt;div&gt;
  3.End :End of the case.
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  Output
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  1.For the Query command: If the current number of contestants is odd, the program should output the poor contestant&amp;rsquo;s name currently even if there is only one contestants, otherwise, just out put &amp;ldquo;No one!&amp;rdquo; (without quotes).
&lt;/div&gt;
&lt;div&gt;
  2.For the End command:
&lt;/div&gt;
&lt;div&gt;
  If the total number of contestants in the data base is even, you should out put &amp;ldquo;Happy BG meeting!!&amp;rdquo;(without quotes),otherwise, you should out put the &amp;ldquo;xxx is so poor. &amp;rdquo;(without quotes) where xxx is the name of the poor one.
&lt;/div&gt;
&lt;div&gt;
  3.Each case should be separated by a blank line.
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  Sample Input
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  2
&lt;/div&gt;
&lt;div&gt;
  Add Magicpig 100
&lt;/div&gt;
&lt;div&gt;
  Add Radium 600
&lt;/div&gt;
&lt;div&gt;
  Add Kingfkong 300
&lt;/div&gt;
&lt;div&gt;
  Add Dynamic 700
&lt;/div&gt;
&lt;div&gt;
  Query
&lt;/div&gt;
&lt;div&gt;
  Add Axing 400
&lt;/div&gt;
&lt;div&gt;
  Query
&lt;/div&gt;
&lt;div&gt;
  Add Inkfish 1000
&lt;/div&gt;
&lt;div&gt;
  Add Carp 800
&lt;/div&gt;
&lt;div&gt;
  End
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  Add Radium 100
&lt;/div&gt;
&lt;div&gt;
  Add Magicpig 200
&lt;/div&gt;
&lt;div&gt;
  End
&lt;/div&gt;
&lt;div&gt;
  Sample Output
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  No one!
&lt;/div&gt;
&lt;div&gt;
  Axing
&lt;/div&gt;
&lt;div&gt;
  Radium is so poor.
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  Happy BG meeting!!
&lt;/div&gt;
&lt;div&gt;
  Problem Source
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  ZSUACM Team Member
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;/div&gt;</description>
    </item>
    <item>
      <title>熬夜完成 sicily1153 马周游解题报告。困死哥了.</title>
      <link>https://ykyi.net/?p=252/</link>
      <pubDate>Tue, 29 Nov 2011 18:11:20 +0000</pubDate>
      <guid>https://ykyi.net/?p=252/</guid>
      <description>&lt;div&gt;
  &lt;p&gt;
    &lt;span style=&#34;line-height: 1.6em;&#34;&gt;唉！！！ 上次交作业写错题目了，做了简单的马周游 sicily 1152。补上新的,应该是sicily 1153.为了解决规模太大的问题。加上了优化算法。&lt;/span&gt;
  &lt;/p&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    中大ACM实验题。
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    （1）原题中文大意
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    中国象棋的马按照象棋的规则在8 x 8 的棋盘上跑64步跑完所有的格子。
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    （2）算法思想及解题用到的主要数据结构
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    从每一个点往下走第二步，会有几点有效的行走位置。 把当前位置记在栈里面，以深度优先的方式进入下一个有效位置。如果下一个有效位置在之前已经走过，则从栈顶弹出上一位置，恢复到调出的位置后尝试未走过的有效位置。利用函数调用时会压栈的特别，用函数递归调用即可解决问题。
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    软之简单的马周游，8 x 8 棋盘的规模非常大。需要在可选下一步中找到最接近正确路线的点。求该点的办法是把所以的可选点先找出，再给这些可选点按权重排序，从最优的解依次向次优，次次优&amp;#8230;..的点试探。重点在权重的算法。这里的权重的计算法则是指一个点的下一次可走的点的个数。
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    主要的数据结构有：
  &lt;/div&gt;
  &lt;div&gt;
    &amp;nbsp;
  &lt;/div&gt;
  &lt;div&gt;
    &lt;pre class=&#34;brush:cpp&#34;&gt;// elocution数组在初始化后会记下每个有效位置的下一步有哪些可走位
&lt;p&gt;// 置.elocution[x][0]用下标0记个数。最多8个有效可走位置。&lt;/p&gt;
&lt;p&gt;char elocution[ELEM_COUNT][9];&lt;/p&gt;
&lt;p&gt;// stamps数组记每个点是否已经走过了。0表示没走过，1表示走过了。&lt;/p&gt;
&lt;p&gt;char stamps[ELEM_COUNT];&lt;/p&gt;
&lt;p&gt;// track数组记路径的顺序。&lt;/p&gt;
&lt;p&gt;char track[ELEM_COUNT];&lt;/p&gt;
&lt;p&gt;通过结合stamps数组和elocution数组可以算出下一步的每个点的权重。&lt;/p&gt;
&lt;p&gt;（3）详细解题思路&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;先初始化一张表。这张表记下了棋盘上所有的30个位置的下一步可走的有效位置.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;写一个一般的递归调用自己的函数，表示马在走第几步时到了哪个位置，然后求出余下的所有可走位置。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;余下的所有位置按照上文提到的权重排序。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;对于排序后的可选点数组，按顺序依次用递归函数尝试。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;递归函数有三个退出条件。1.下一个要尝试的点已经走过了，2.试完了所有的可选下一步无解。3.走到了最后一步，即得解！&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;（4）算法描述&lt;/p&gt;
&lt;p&gt;初如化上文提到的elocution数组，清空stamps和tracks.从起点开始调用递归函数。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://ykyi.net&#34;&gt;http://ykyi.net&lt;/a&gt;  zausiu&#39;s blog.&lt;/p&gt;
&lt;p&gt;（5）程序注释清单&lt;/p&gt;
&lt;p&gt;#include &amp;lt;iostream&amp;gt;&lt;/p&gt;
&lt;p&gt;#include &amp;lt;cstring&amp;gt;&lt;/p&gt;
&lt;p&gt;#include &amp;lt;cstdlib&amp;gt;&lt;/p&gt;
&lt;p&gt;#include &amp;lt;vector&amp;gt;&lt;/p&gt;
&lt;p&gt;#include &amp;lt;csetjmp&amp;gt;&lt;/p&gt;
&lt;p&gt;//#include &amp;lt;cassert&amp;gt;&lt;/p&gt;
&lt;p&gt;using namespace std;&lt;/p&gt;
&lt;p&gt;#define  ROW_NUM     8&lt;/p&gt;
&lt;p&gt;#define  COLUMN_NUM  8&lt;/p&gt;
&lt;p&gt;#define  ELEM_COUNT ROW_NUM * COLUMN_NUM&lt;/p&gt;
&lt;p&gt;jmp_buf jmpbuffer;  // 很深的函数递归调用时用longjmp快速退出.&lt;/p&gt;
&lt;p&gt;// elocution数组在初始化后会记下每个有效位置的下一步有哪些可走位&lt;/p&gt;
&lt;p&gt;// 置.elocution[x][0]用下标0记个数。最多8个有效可走位置。&lt;/p&gt;
&lt;p&gt;char elocution[ELEM_COUNT][9];&lt;/p&gt;
&lt;p&gt;// stamps数组记每个点是否已经走过了。0表示没走过，1表示走过了。&lt;/p&gt;
&lt;p&gt;char stamps[ELEM_COUNT];&lt;/p&gt;
&lt;p&gt;struct coordinate  // 二维坐标&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;char _x;  // start from zero.&lt;/p&gt;
&lt;p&gt;char _y;&lt;/p&gt;
&lt;p&gt;};&lt;/p&gt;
&lt;p&gt;// 作标转序号&lt;/p&gt;
&lt;p&gt;char coordinate2serial_num(coordinate co)&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;char num = co._x * COLUMN_NUM + co._y + 1;&lt;/p&gt;
&lt;p&gt;return num;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;// 序号转坐标&lt;/p&gt;
&lt;p&gt;coordinate serial_num2coordinate(char sn)&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;coordinate co;&lt;/p&gt;
&lt;p&gt;co._x = (sn - 1) / COLUMN_NUM;&lt;/p&gt;
&lt;p&gt;co._y = sn - co._x * COLUMN_NUM - 1;&lt;/p&gt;
&lt;p&gt;return co;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;// ((x:1;y:-2),(x:2;y:-1),(x:2;y:1),(x:1;y:2) (x:-1;y:2),(x:-2;y:1),(x:-2;y:-1),(x:-1;y:-2));&lt;/p&gt;
&lt;p&gt;char increments[8][2] =&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;1, -2, 2, -1, 2, 1, 1, 2,&lt;/p&gt;
&lt;p&gt;-1, 2, -2, 1, -2, -1, -1, -2&lt;/p&gt;
&lt;p&gt;};&lt;/p&gt;
&lt;p&gt;void next_step(char pos, char steps[])  // 把位置在pos序号的点的每一个下一个可选位置记在数组中。&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;char valid_count = 0;&lt;/p&gt;
&lt;p&gt;coordinate co = serial_num2coordinate(pos);&lt;/p&gt;
&lt;p&gt;coordinate tmp;&lt;/p&gt;
&lt;p&gt;char serial_num;&lt;/p&gt;
&lt;p&gt;for ( int i = 0; i &amp;lt; 8; i++ )&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;tmp._x = co._x + increments[i][0];&lt;/p&gt;
&lt;p&gt;tmp._y = co._y + increments[i][1];&lt;/p&gt;
&lt;p&gt;if ( tmp._x &amp;lt; 0 || tmp._x &amp;gt;= ROW_NUM || tmp._y &amp;lt; 0 || tmp._y &amp;gt;= COLUMN_NUM )  // 保证位置有效&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;continue;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;serial_num = coordinate2serial_num(tmp);&lt;/p&gt;
&lt;p&gt;if ( serial_num &amp;gt;= 1 &amp;amp;&amp;amp; serial_num &amp;lt;= ELEM_COUNT )&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;valid_count++;&lt;/p&gt;
&lt;p&gt;steps[valid_count] = serial_num;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;else&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;cerr &amp;lt;&amp;lt; &amp;ldquo;Not expected to reach here.\n&amp;rdquo;;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;steps[0] = valid_count;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;// 下面的逻辑以每个点的下一步可跳点的数目作为权重排序。&lt;/p&gt;
&lt;p&gt;struct pos_weight&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;char _pos;&lt;/p&gt;
&lt;p&gt;char _weight;&lt;/p&gt;
&lt;p&gt;};&lt;/p&gt;
&lt;p&gt;// 又是用递归。这里为了实现快速排序&lt;/p&gt;
&lt;p&gt;int partition(pos_weight poses[], int low, int high)&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;pos_weight pivot = poses[low];&lt;/p&gt;
&lt;p&gt;while (low &amp;lt; high)&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;while (low &amp;lt; high &amp;amp;&amp;amp; pivot._weight &amp;lt; poses[high]._weight)&lt;/p&gt;
&lt;p&gt;high&amp;ndash;;&lt;/p&gt;
&lt;p&gt;poses[low] = poses[high];&lt;/p&gt;
&lt;p&gt;while (low &amp;lt; high &amp;amp;&amp;amp; pivot._weight &amp;gt;= poses[low]._weight)&lt;/p&gt;
&lt;p&gt;low++;&lt;/p&gt;
&lt;p&gt;poses[high] = poses[low];&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;poses[low] = pivot;&lt;/p&gt;
&lt;p&gt;return low;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;// 快速排序。&lt;/p&gt;
&lt;p&gt;void quick_sort_steps(pos_weight poses[], int low, int high)&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;if ( low &amp;lt; high )&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;int pivot_loc = partition(poses, low, high);&lt;/p&gt;
&lt;p&gt;quick_sort_steps(poses, low, pivot_loc-1);&lt;/p&gt;
&lt;p&gt;quick_sort_steps(poses, pivot_loc+1, high);&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;void rearrage_steps(char poses[], int len) // poese里放置了下一个位置数组。Len是数组长度。&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;char weight, pos, next_step_count;&lt;/p&gt;
&lt;p&gt;vector&amp;lt;pos_weight&amp;gt; vec(len);&lt;/p&gt;
&lt;p&gt;for ( int i = 0; i &amp;lt; len; i++ ) // 计算权重.&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;weight = 0;&lt;/p&gt;
&lt;p&gt;pos = poses[i];&lt;/p&gt;
&lt;p&gt;next_step_count = elocution[pos-1][0];&lt;/p&gt;
&lt;p&gt;for ( int j = 0; j &amp;lt; next_step_count; j++ )&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;char next_step_pos = elocution[pos-1][j+1];&lt;/p&gt;
&lt;p&gt;if ( 0 == stamps[next_step_pos-1] )&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;weight++;  // 如果有一下一跳点没走过则权重加1.&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;vec[i]._pos = pos;&lt;/p&gt;
&lt;p&gt;vec[i]._weight = weight;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;quick_sort_steps(&amp;amp;vec[0], 0, len-1);  // 根据权重排序.&lt;/p&gt;
&lt;p&gt;for ( int i = 0; i &amp;lt; len; i++ ) // 把排序后的位置写回原始数组.&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;poses[i] = vec[i]._pos;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;void init_elocution()&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;memset(stamps, 0, sizeof(stamps));&lt;/p&gt;
&lt;p&gt;for ( int i = 1; i &amp;lt;= ELEM_COUNT; i++ )&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;next_step(i, elocution[i-1]);&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;char track[ELEM_COUNT];&lt;/p&gt;
&lt;p&gt;void run_horse(char start_pos, char step_count) // step_count [0 &amp;ndash; 64)&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;// 如果已经经过这点就立即退出函数。&lt;/p&gt;
&lt;p&gt;if ( 1 == stamps[start_pos-1] )&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;return;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;track[step_count] = start_pos;&lt;/p&gt;
&lt;p&gt;if ( step_count == COLUMN_NUM * ROW_NUM - 1 )  // 是不是最后一步。&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;for ( int i = 0; i &amp;lt; sizeof(track); i++ )&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;cout &amp;lt;&amp;lt; (int)track[i];&lt;/p&gt;
&lt;p&gt;if ( i + 1 != sizeof(track) )&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;cout &amp;lt;&amp;lt; &amp;quot; &amp;ldquo;;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;cout &amp;lt;&amp;lt; endl;&lt;/p&gt;
&lt;p&gt;longjmp(jmpbuffer, 0x1);&lt;/p&gt;
&lt;p&gt;return;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;// 记下已经走了这一步。&lt;/p&gt;
&lt;p&gt;stamps[start_pos-1] = 1;   rearrage_steps(elocution[start_pos-1]+1, elocution[start_pos-1][0]);&lt;/p&gt;
&lt;p&gt;for ( int i = 0; i &amp;lt; elocution[start_pos-1][0]; i++ )&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;run_horse(elocution[start_pos-1][i+1], step_count+1);&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;stamps[start_pos-1] = 0;  // 试完了所有可走步.退出这个函数.重置这个位置为没有走过。&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;int main(int argc, char* argv[])&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;int pos;&lt;/p&gt;
&lt;p&gt;vector&amp;lt;int&amp;gt; vec;&lt;/p&gt;
&lt;p&gt;while(true)&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;cin &amp;gt;&amp;gt; pos;&lt;/p&gt;
&lt;p&gt;if (pos==-1)&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;break;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;vec.push_back(pos);&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;for ( int i = 0; i &amp;lt; vec.size(); i++ )&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;if(setjmp(jmpbuffer) == 0)  // 为了很深的递归函数快速回退到这里。&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;init_elocution();&lt;/p&gt;
&lt;p&gt;memset(track, 0, sizeof(track));&lt;/p&gt;
&lt;p&gt;memset(stamps, 0, sizeof(stamps));&lt;/p&gt;
&lt;p&gt;run_horse(vec[i], 0);&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;return 0;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;
  &amp;nbsp;
&lt;/p&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
  （6）该算法的时间复杂度是 O(8 ^ (m * n)) &amp;nbsp; m,n分别为棋盘的长和宽。
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  /////////////////// 原题目如下:
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  1153. 马的周游问题
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  Description
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  和题目C同样的任务，这里只是把棋盘扩大到标准的国际象棋。对这样一个8 * 8的棋盘用同样的方法编号如下：
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  1 &amp;nbsp; &amp;nbsp; 2 &amp;nbsp; &amp;nbsp; 3 &amp;nbsp; &amp;nbsp; &amp;nbsp; 4 &amp;nbsp; &amp;nbsp; 5 &amp;nbsp; &amp;nbsp; 6 &amp;nbsp; &amp;nbsp; &amp;nbsp; 7 &amp;nbsp; &amp;nbsp; 8
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  9 &amp;nbsp; &amp;nbsp; 10 &amp;nbsp; &amp;nbsp; &amp;nbsp; 11 &amp;nbsp; &amp;nbsp;12 &amp;nbsp; &amp;nbsp; &amp;nbsp; 13 &amp;nbsp; &amp;nbsp;14 &amp;nbsp; &amp;nbsp; &amp;nbsp; 15 &amp;nbsp; &amp;nbsp;16
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  17 &amp;nbsp; &amp;nbsp;18 &amp;nbsp; &amp;nbsp; &amp;nbsp; 19 &amp;nbsp; &amp;nbsp;20 &amp;nbsp; &amp;nbsp; &amp;nbsp; 21 &amp;nbsp; &amp;nbsp;22 &amp;nbsp; &amp;nbsp; &amp;nbsp; 23 &amp;nbsp; &amp;nbsp;24
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  25 &amp;nbsp; &amp;nbsp;26 &amp;nbsp; &amp;nbsp; &amp;nbsp; 27 &amp;nbsp; &amp;nbsp;28 &amp;nbsp; &amp;nbsp; &amp;nbsp; 29 &amp;nbsp; &amp;nbsp;30 &amp;nbsp; &amp;nbsp; &amp;nbsp; 31 &amp;nbsp; &amp;nbsp;32
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  33 &amp;nbsp; &amp;nbsp;34 &amp;nbsp; &amp;nbsp; &amp;nbsp; 35 &amp;nbsp; &amp;nbsp;36 &amp;nbsp; &amp;nbsp; &amp;nbsp; 37 &amp;nbsp; &amp;nbsp;38 &amp;nbsp; &amp;nbsp; &amp;nbsp; 39 &amp;nbsp; &amp;nbsp;40
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  41 &amp;nbsp; &amp;nbsp;42 &amp;nbsp; &amp;nbsp; &amp;nbsp; 43 &amp;nbsp; &amp;nbsp;44 &amp;nbsp; &amp;nbsp; &amp;nbsp; 45 &amp;nbsp; &amp;nbsp;46 &amp;nbsp; &amp;nbsp; &amp;nbsp; 47 &amp;nbsp; &amp;nbsp;48
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  49 &amp;nbsp; &amp;nbsp;50 &amp;nbsp; &amp;nbsp; &amp;nbsp; 51 &amp;nbsp; &amp;nbsp;52 &amp;nbsp; &amp;nbsp; &amp;nbsp; 53 &amp;nbsp; &amp;nbsp;54 &amp;nbsp; &amp;nbsp; &amp;nbsp; 55 &amp;nbsp; &amp;nbsp;56
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  57 &amp;nbsp; &amp;nbsp;58 &amp;nbsp; &amp;nbsp; &amp;nbsp; 59 &amp;nbsp; &amp;nbsp;60 &amp;nbsp; &amp;nbsp; &amp;nbsp; 61 &amp;nbsp; &amp;nbsp;62 &amp;nbsp; &amp;nbsp; &amp;nbsp; 63 &amp;nbsp; &amp;nbsp;64
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  Input
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  输入有若干行。每行一个整数N(1&lt;=N&lt;=64)，表示马的起点。最后一行用-1表示结束，不用处理。
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  Output
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  对输入的每一个起点，求一条周游线路。对应地输出一行，有64个整数，从起点开始按顺序给出马每次经过的棋盘方格的编号。相邻的数字用一个空格分开。
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  Sample Input
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  4
&lt;/div&gt;
&lt;div&gt;
  -1
&lt;/div&gt;
&lt;div&gt;
  Sample Output
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  注意：如果起点和输入给定的不同，重复多次经过同一方格或者有的方格没有被经过，都会被认为是错误的。
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;div&gt;
  &amp;nbsp;
&lt;/div&gt;
&lt;/div&gt;</description>
    </item>
    <item>
      <title>又是数组越界造成的bug.</title>
      <link>https://ykyi.net/?p=246/</link>
      <pubDate>Tue, 29 Nov 2011 15:19:10 +0000</pubDate>
      <guid>https://ykyi.net/?p=246/</guid>
      <description>&lt;div&gt;
  &lt;p&gt;
    又一次遇到数组越界造成的奇怪的，难以调试的，诡异的&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;bug.&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    前几天做&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;ACM&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;题。&amp;lsquo;简单的马周游&amp;rsquo;。&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    见&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;:&amp;nbsp;&lt;/span&gt;&lt;a href=&#34;../2011/11/acm-%E9%A9%AC%E5%91%A8%E6%B8%B8%E8%A7%A3%E9%A2%98%E6%8A%A5%E5%91%8A/&#34;&gt;http://ykyi.net/2011/11/acm-%E9%A9%AC%E5%91%A8%E6%B8%B8%E8%A7%A3%E9%A2%98%E6%8A%A5%E5%91%8A/&lt;/a&gt;
  &lt;/p&gt;
  &lt;p&gt;
    因为我的解法用了函数递归调用，函数求到最终解的栈的调用层次非常深。第一版用置一个全局变量的方式让这么深调用的函数快速依次退出。但我也知道还有另外一种解法就是用&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;C&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;语言的&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;setjmp&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;和&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;longjmp&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;。用这两个函数可以快速退栈。&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    今天晚上就想用&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;setjmp&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;和&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;longjmp&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;改写一下。本来以为是非常简单的事情。结果改完以的程序只能正确求解第一个请求，然后程序看起来就像是死了。&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;Debug&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;时发现程序似乎跑飞了。哎&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;脑子不灵光，发现程序跑飞竟然没有立即想到是数组越界把堆栈写坏了&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;。因为我改动的代码非常少，只是用&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;setjmp&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;和&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;longjmp&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;快速退出递归取代之前的稍微比较慢的做法。而其它的代码改动的非常之少。于是我当时分析错误的出发点就是比较两份代码的异同。比较来比较去，就只有退出方式不同而已。相当相当地困惑。费了很多时间都没有找到原因。&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    实在搞不定了。冲了个热水澡，又回来看代码。还是没有发现这个改动在哪里引入了错误。不断反复地看代码，突然灵光一现看到写一个全局数组的语句，下标变量越界！越界！越界！！！啊&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;~~&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;惊喜！于是把数组下标的相关的代码纠正了，于是&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;setjmp&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;版本的代码也运行正常啊。&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    这次的经验是。操作数组的时候一定要一定要一定要非常非常非常之小心&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;~~&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;在调试程序发现程序跑飞的情况下马上要意识到是写坏了堆栈。&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    另外还有一个疑问是第一版的代码也有写坏栈的问题为什么就一切正常呢。这就是&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;C/C++&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;程序数组危险的地方啊&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;~~&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;第一版本的代码退栈的方式和第二版不一样，于是这个&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;bug&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;就在第一版隐藏了起来。于是第二版出问题时我的思路集中在比较代码差异是如何引入问题的。&lt;strong&gt;而这个&lt;/strong&gt;&lt;/span&gt;&lt;strong&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;bug&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;并不是新代码引入的，而是在旧代码隐藏起来的，第二代的新代码让触发了这个&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;bug&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;。&lt;/span&gt;&lt;/strong&gt;
  &lt;/p&gt;
  &lt;p&gt;
    总结下经验：
  &lt;/p&gt;
  &lt;p&gt;
    一定要一定要非常小心&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;C/C++&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;的数组越界问题啊！！！操作很多数组时，有很多下标要计算时。千万要注意是从0还是从1开始计算下标。要根据约定多下诊断！！！及时发现隐藏的错误。越界写数组的bug有时发生，可能在引入的当时被隐藏，隐藏的很深很深。但越界读数组的bug隐藏得更深更深更深啊。&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    copyright ykyi.net
  &lt;/p&gt;
&lt;/div&gt;</description>
    </item>
    <item>
      <title>中大ACM题.商人的宣传解题报告.</title>
      <link>https://ykyi.net/?p=243/</link>
      <pubDate>Sat, 26 Nov 2011 10:35:30 +0000</pubDate>
      <guid>https://ykyi.net/?p=243/</guid>
      <description>&lt;h1 id=&#34;description&#34;&gt;Description&lt;/h1&gt;
&lt;p&gt;Bruce是K国的商人，他在A州成立了自己的公司，这次他的公司生产出了一批性能很好的产品，准备宣传活动开始后的第L天到达B州进行新品拍卖，期间Bruce打算将产品拿到各个州去做推销宣传,以增加其影响力。&lt;/p&gt;
&lt;p&gt;K国有很多个州,每个州都与其他一些州相邻,但是K国对商人作宣传却有一些很奇怪的规定：&lt;br&gt;
1、 商人只能从某些州到达另外一些州，即连通路线是单向的，而且有些州可能是到达不了的。&lt;br&gt;
2、 商人不允许在同一个州连续宣传两天或以上，每天宣传完必须离开该州。&lt;br&gt;
3、 商人可以多次来到同一个州进行宣传。&lt;/p&gt;
&lt;p&gt;&amp;ldquo;我必须找出一条影响力最大的路线才行&amp;rdquo;，Bruce想，&amp;ldquo;但我首先必须知道到底有多少这种符合规定的宣传路线可供我选择。&amp;ldquo;现在Bruce把任务交给了你。并且出于考虑以后的需要，你还要帮他算出给出的两州之间的路线的总数。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h1 id=&#34;input&#34;&gt;Input&lt;/h1&gt;
&lt;p&gt;输入文件第一行包含三个整数n,m,L（1≤n,L≤100），分别表示K国的州数、连通路线的数量，以及多少天后必须到达B州。接下来有m行，每行一队整数x,y（1≤x,y≤n），表示商人能从x州到达y州。&lt;br&gt;
第m+2行为一个整数q（1≤q≤100），表示Bruce有q个询问。下面q行每行两个整数A,B（1≤A,B≤n），即A、B州的位置。&lt;/p&gt;
&lt;h1 id=&#34;output&#34;&gt;Output&lt;/h1&gt;
&lt;p&gt;输出文件包含q行，每行一个整数t，为所求的从A州到B州满足上述规定的路线总数。&lt;br&gt;
输入数据中的询问将保证答案t在长整数范围内，即t&amp;lt;2&lt;sup&gt;31&lt;/sup&gt;。&lt;/p&gt;
&lt;h1 id=&#34;sample-input&#34;&gt;Sample Input&lt;/h1&gt;
&lt;pre&gt;4 5 6
1 2
2 3
3 4
4 1
2 4
2
1 4
4 2&lt;/pre&gt;
&lt;h1 id=&#34;sample-output&#34;&gt;Sample Output&lt;/h1&gt;
&lt;pre&gt;2 1&lt;/pre&gt;
&lt;div&gt;
  &lt;p&gt;
    1.&amp;nbsp;原题中文大意.
  &lt;/p&gt;
  &lt;p&gt;
    商人的宣传即是一个有向图的问题。有一个有向图。该图的每条件权重一样，从图中任意一点a&lt;span style=&#34;font-family: 宋体;&#34;&gt;刚好通过&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;L&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;步到达另一点&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;b&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;有多少条路线。&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    2.&amp;nbsp;算法思想及解题思路.
  &lt;/p&gt;
  &lt;p&gt;
    使用了动态规划算法。令&amp;nbsp;dp[num][dest]&amp;nbsp;&lt;span style=&#34;font-family: 宋体;&#34;&gt;表示从起点通过&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;num&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;条边到达终点共有多少种走法。&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    先由已经知条件易得从起点通过一条它的邻接边到达它的所有邻接点共有一条路线。即&amp;nbsp;dp[1][&lt;span style=&#34;font-family: 宋体;&#34;&gt;邻接点&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;]&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;易求得。而&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;dp[x][y]&amp;nbsp;=&amp;nbsp;sum(&amp;nbsp;dp[x-1][&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;可以一条邻接边到达&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;y&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;的点&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;]&amp;nbsp;)&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;。&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    3.&amp;nbsp;主要数数据结构&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;.&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    主要数据结构为三个数组。这本个数组都不用下标为&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;的元素。&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    char&amp;nbsp;odgree[MAX_VERTICES_NUM+1];
  &lt;/p&gt;
  &lt;p&gt;
    下标为每个顶点的编号&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;表示每个顶点的出度&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;.&amp;nbsp;&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    int&amp;nbsp;routine[MAX_VERTICES_NUM+1][MAX_VERTICES_NUM+1];
  &lt;/p&gt;
  &lt;p&gt;
    &amp;lsquo;路由表&amp;rsquo;&amp;nbsp;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;routine[x][n]&amp;nbsp;=&amp;nbsp;y&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;表示从顶点&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;x&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;经它的第&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;n&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;条邻接边可以到达顶点&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;y.&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    int&amp;nbsp;dp[MAX_VERTICES_NUM+1][MAX_VERTICES_NUM+1];
  &lt;/p&gt;
  &lt;p&gt;
    这个数组即第二节提到的&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;dp&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;数组，&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;dp[L][x]&amp;nbsp;=&amp;nbsp;num&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;从起点开始经&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;L&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;条边走到顶点&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;x&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;共有&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;num&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;种走法。&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    &amp;nbsp;
  &lt;/p&gt;
  &lt;p&gt;
    4.&amp;nbsp;逐步求精算法描述（含过程及变量说明）&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;;&lt;/span&gt;
  &lt;/p&gt;
  &lt;p&gt;
    从已知条件初始化&amp;nbsp;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;odgree&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;和&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;routine&amp;nbsp;&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;数组&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;.&lt;/span&gt;
  &lt;/p&gt;
  &lt;pre class=&#34;brush:cpp&#34;&gt;bzero(odgree, sizeof(odegree));

for(int x,y, i = 0; i &amp;lt; m; i++)

{

scanf(&#34;%d %d&#34;, &amp;x, &amp;y);

odgree[x]++;

routine[x][ odgree[x] ] = y;

}



下面的cal函数输入起点顶点和终点顶点，返回共有多少种走法。

int cal(char start, char dest)

{

memset(dp, 0, sizeof(dp));



for ( int i = 1; i &amp;lt;= odgree[start]; i++ )  // 遍历起点的每一条邻接边

{

dp[1][ routine[start][i] ]++;  //  初始时经过一邻接边到达别一点的走法有几种.



}



for ( int i = 2; i &amp;lt;= L; i++ )   // 一直走到第L步.

{

for ( int j = 1; j &amp;lt;= n; j++ )  // 遍历每一个顶点.

{

for ( int k = 1; k &amp;lt;= odgree[j]; k++ )  // 该顶点的第一条邻接边

{

// 上文提到的递推公式。

dp[i][ routine[j][k] ] += dp[i-1][j];

}

}

}



return dp[L][dest];  // 返回结果

}&lt;/pre&gt;
&lt;p&gt;
  &amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
  5.&amp;nbsp;程序注释清单
&lt;/p&gt;
&lt;pre class=&#34;brush:cpp&#34;&gt;#include &amp;lt;cstdio&amp;gt;

#include &amp;lt;cstdlib&amp;gt;

#include &amp;lt;memory&amp;gt;

#include &amp;lt;cstring&amp;gt;

#include &amp;lt;vector&amp;gt;



using namespace std;



const int MAX_VERTICES_NUM = 100;  // 最多多少个顶点.

int n, m, L, q;  // 实际n个点、m条边，L 为期限.q为有多少个询问.

static char odgree[MAX_VERTICES_NUM+1];  // 记每个点的出度.不用下标为0的元素.

static int routine[MAX_VERTICES_NUM+1][MAX_VERTICES_NUM+1];  // table[x][y] 表示x点经它的第y条边可以去到哪个点.

static int dp[MAX_VERTICES_NUM+1][MAX_VERTICES_NUM+1];  // dp[x][y] 表示经x条边，可以从某点到 y 点.



int cal(char start, char dest)

{

memset(dp, 0, sizeof(dp));



for ( int i = 1; i &amp;lt;= odgree[start]; i++ )  // 遍历起点的每一条邻接边.

{

dp[1][ routine[start][i] ]++;  // 初始时经过一步到达别一点的走法.

}



for ( int i = 2; i &amp;lt;= L; i++ )   // 一直走到第 L 步.

{

for ( int j = 1; j &amp;lt;= n; j++ )  // 遍历每一个点.

{

for ( int k = 1; k &amp;lt;= odgree[j]; k++ )  // 该点的每一个邻接点.

{

dp[i][ routine[j][k] ] += dp[i-1][j];

}

}

}



return dp[L][dest];

}



int main(int argc, char* argv[])

{

while ( EOF != scanf(&#34;%d %d %d&#34;, &amp;n, &amp;m, &amp;L) )

{

memset(odgree, 0, sizeof(odgree));

for(int x,y, i = 0; i &amp;lt; m; i++)

{

scanf(&#34;%d %d&#34;, &amp;x, &amp;y);

odgree[x]++;

routine[x][ odgree[x] ] = y;

}



scanf(&#34;%d&#34;, &amp;q);

vector&amp;lt;int&amp;gt; results;

for ( int start,dest, i = 0; i &amp;lt; q; i++)

{

scanf(&#34;%d %d&#34;, &amp;start, &amp;dest);

results.push_back(cal(start, dest));

}

for ( int i = 0; i &amp;lt; results.size(); i++ )

{

printf(&#34;%d\n&#34;, results[i]);

}



}

return 0;

}
&lt;/pre&gt;
&lt;p&gt;
  &amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
  6.&amp;nbsp;测试数据
&lt;/p&gt;
&lt;p&gt;
  4&amp;nbsp;5&amp;nbsp;6
&lt;/p&gt;
&lt;p&gt;
  1&amp;nbsp;2
&lt;/p&gt;
&lt;p&gt;
  2&amp;nbsp;3
&lt;/p&gt;
&lt;p&gt;
  3&amp;nbsp;4
&lt;/p&gt;
&lt;p&gt;
  4&amp;nbsp;1
&lt;/p&gt;
&lt;p&gt;
  2&amp;nbsp;4
&lt;/p&gt;
&lt;p&gt;
  5
&lt;/p&gt;
&lt;p&gt;
  1&amp;nbsp;4
&lt;/p&gt;
&lt;p&gt;
  4&amp;nbsp;2
&lt;/p&gt;
&lt;p&gt;
  2&amp;nbsp;1
&lt;/p&gt;
&lt;p&gt;
  1&amp;nbsp;3
&lt;/p&gt;
&lt;p&gt;
  3&amp;nbsp;4
&lt;/p&gt;
&lt;p&gt;
  2
&lt;/p&gt;
&lt;p&gt;
  1
&lt;/p&gt;
&lt;p&gt;
  2
&lt;/p&gt;
&lt;p&gt;
  1
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
  &amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
  &amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
  7.&amp;nbsp;对时间复杂度，空间复杂度方面的分析、估算及程序优化的分析和改进&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;.&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
  本解决方法的时间复杂度为O(L*n*n)&lt;span style=&#34;font-family: 宋体;&#34;&gt;，空间复杂度为&lt;/span&gt;&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;O(n*n).&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
  用动态规划解此题的时间复杂度优于用邻接矩阵表示图然后用图的乘法解出。后者的时间复杂志为&lt;span style=&#34;font-family: Times New Roman;&#34;&gt;O(L*n*n*n)&lt;/span&gt;&lt;span style=&#34;font-family: 宋体;&#34;&gt;。&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;</description>
    </item>
  </channel>
</rss>
