Sicily 1031 Campus 解题报告.

  1 原题中文大意;   Sicily 1031 Campus实际上就是求一个图中给出两点的最短路径的问题。   2 算法思想及解题用到的主要数据结构;   用 dijkstra 算法求给定两点的最短路径.   按路径长度递增次序产生最短路径算法: 把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的路径权值之和。   3  逐步求精算法描述   用邻接矩阵存放图.1. 初使时令 S={V0},T={其余顶点},T中顶点对应的距离值 若存在,d(V0,Vi)为弧上的权值 若不存在,d(V0,Vi)为∝ 2. 从T中选取一个其距离值为最小的顶点W且不在S中,加入S 3. 对T中顶点的距离值进行修改:若加进W作中间顶点,从V0到Vi的 距离值比不加W的路径要短,则修改此距离值 重复上述步骤2、3,直到S中包含所有顶点,即S=T为止   3 程序注释清单 // 这份代码通不过sicily。有case错误。我实在找不到原因。   #include <map> #include <vector> #include <string> #include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <cassert> #define INFINITE 0x0FFFFFFF // 这个类的函数几乎不做参数有效性的检查. class graph_t ...

December 26, 2011 · 4 min · kamus

ACM 马周游解题报告

<p> &nbsp; </p> <p> &nbsp; </p> <p> &nbsp; </p> <h3 style="text-align: left; "> <span style="font-size: 14px; ">简单的马周游问题</span> </h3> <p> &nbsp; </p> <p> &nbsp; </p> <p> </center> </div> <p> &nbsp; </p> <div> &nbsp; </div> <div> <span style="font-size:14px;">Description</span> </div> <div> &nbsp; </div> <div> <span style="font-size:14px;">在一个5 * 6的棋盘中的某个位置有一只马,如果它走29步正好经过除起点外的其他位置各一次,这样一种走法则称马的周游路线,试设计一个算法,从给定的起点出发,找出它的一条周游路线。</span> </div> <div> &nbsp; </div> <div> <span style="font-size:14px;">为了便于表示一个棋盘,我们按照从上到下,从左到右对棋盘的方格编号,如下所示:</span> </div> <div> &nbsp; </div> <div> <span style="font-size:14px;">1 &nbsp; &nbsp; 2 &nbsp; &nbsp; 3 &nbsp; &nbsp; &nbsp; 4 &nbsp; &nbsp; 5 &nbsp; &nbsp; 6</span> </div> <div> &nbsp; </div> <div> <span style="font-size:14px;">7 &nbsp; &nbsp; 8 &nbsp; &nbsp; 9 &nbsp; &nbsp; &nbsp; 10 &nbsp; &nbsp;11 &nbsp; &nbsp; &nbsp; 12</span> </div> <div> &nbsp; </div> <div> <span style="font-size:14px;">13 &nbsp; &nbsp;14 &nbsp; &nbsp; &nbsp; 15 &nbsp; &nbsp;16 &nbsp; &nbsp; &nbsp; 17 &nbsp; &nbsp;18</span> </div> <div> &nbsp; </div> <div> <span style="font-size:14px;">19 &nbsp; &nbsp;20 &nbsp; &nbsp; &nbsp; 21 &nbsp; &nbsp;22 &nbsp; &nbsp; &nbsp; 23 &nbsp; &nbsp;24</span> </div> <div> &nbsp; </div> <div> <span style="font-size:14px;">25 &nbsp; &nbsp;26 &nbsp; &nbsp; &nbsp; 27 &nbsp; &nbsp;28 &nbsp; &nbsp; &nbsp; 29 &nbsp; &nbsp;30</span> </div> <div> &nbsp; </div> <div> <span style="font-size:14px;">马的走法是&ldquo;日&rdquo;字形路线,例如当马在位置15的时候,它可以到达2、4、7、11、19、23、26和28。但是规定马是不能跳出棋盘外的,例如从位置1只能到达9和14。</span> </div> <div> &nbsp; </div> <div> <span style="font-size:14px;">Input</span> </div> <div> &nbsp; </div> <div> <span style="font-size:14px;">输入有若干行。每行一个整数N(1<=N<=30),表示马的起点。最后一行用-1表示结束,不用处理。</span> </div> <div> &nbsp; </div> <div> <span style="font-size:14px;">Output</span> </div> <div> &nbsp; </div> <div> <span style="font-size:14px;">对输入的每一个起点,求一条周游线路。对应地输出一行,有30个整数,从起点开始按顺序给出马每次经过的棋盘方格的编号。相邻的数字用一个空格分开。</span> </div> <div> &nbsp; </div> <div> <span style="font-size:14px;">Sample Input</span> </div> <div> &nbsp; </div> <div> <span style="font-size:14px;">4</span> </div> <div> <span style="font-size:14px;">-1</span> </div> <div> <span style="font-size:14px;">Sample Output</span> </div> <div> &nbsp; </div> <div> <span style="font-size:14px;">注意:如果起点和输入给定的不同,重复多次经过同一方格或者有的方格没有被经过,都会被认为是错误的。</span> </div> <div> &nbsp; </div> <div> &nbsp; </div> <div> <span style="font-size:14px;">(1)原题中文大意</span> </div> <div> &nbsp; </div> <div> <span style="font-size:14px;">中国象棋的马按照象棋的规则在5 x 6 的棋盘上跑30步跑完所有的格子。</span> </div> <div> &nbsp; </div> <div> &nbsp; </div> <div> &nbsp; </div> <div> <span style="font-size:14px;">(2)算法思想及解题用到的主要数据结构</span> </div> <div> &nbsp; </div> <div> &nbsp; </div> <div> &nbsp; </div> <div> <span style="font-size:14px;">从每一个点往下走第二步,会有几点有效的行走位置。 把当前位置记在栈里面,以深度优先的方式进入下一个有效位置。如果下一个有效位置在之前已经走过,则从栈顶弹出上一位置,恢复到调出的位置后尝试未走过的有效位置。利用函数调用时会压栈的特别,用函数递归调用即可解决问题。</span> </div> <div> &nbsp; </div> <div> &nbsp; </div> <div> &nbsp; </div> <div> <span style="font-size:14px;">(3)详细解题思路</span> </div> <div> &nbsp; </div> <div> <span style="font-size:14px;">1. 先初始化一张表。这张表记下了棋盘上所有的30个位置的下一步可走的有效位置.</span> </div> <div> &nbsp; </div> <div> <span style="font-size:14px;">2. 写一个一般的递归调用自己的函数,表示马在走第几步时到了哪个位置,然后尝试走余下的所有可走位置。</span> </div> <div> &nbsp; </div> <div> <span style="font-size:14px;">3. 递归函数有两个退出条件。要么下一个要尝试的点已经走过了,要么走到了最后一步,即得解!</span> </div> <div> &nbsp; </div> <div> &nbsp; </div> <div> &nbsp; </div> <div> <span style="font-size:14px;">(4)逐步求精算法描述</span> </div> <div> &nbsp; </div> <div> <span style="font-size:14px;">用一个数组记下来经过的点。</span> </div> <div> &nbsp; </div> <div> &nbsp; </div> <div> &nbsp; </div> <div> <span style="font-size:14px;">(5)程序注释清单</span> </div> <div> &nbsp; </div> <div> <pre class="brush:cpp">#include &lt;iostream&gt; #include <cstring> #include <cstdlib> #include <vector> using namespace std; const static char row_num = 5; // 5行 const static char column_num = 6; // 6列 // 这个全局数组在初始化后会记下每30个有效位置的下一步可走位置. // elocution[x][0]记个数。最多8个有效可走位置。 char elocution[30][9]; struct coordinate // 坐标. { char _x; // start from zero. char _y; }; // 坐标转序号的函数。 char coordinate2serial_num(coordinate co) { char num = co._x * column_num + co._y + 1; return num; } // 序号转坐标的函数。 coordinate serial_num2coordinate(char sn) { coordinate co; co._x = (sn - 1) / column_num; co._y = sn - co._x * column_num - 1; return co; } // 增量数组. char increments[8][2] = { 1, -2, 2, -1, 2, 1, 1, 2, -1, 2, -2, 1, -2, -1, -1, -2 }; // 得用增量数组来计算每一个位置的下一步有效位置。记到steps里面. void next_step(char pos, char steps[]) { char valid_count = 0; coordinate co = serial_num2coordinate(pos); coordinate tmp; char serial_num; for ( int i = 0; i < 8; i++ ) { tmp._x = co._x + increments[i][0]; tmp._y = co._y + increments[i][1]; if ( tmp._x < 0 || tmp._x > 4 || tmp._y < 0 || tmp._y > 5 ) { continue; } serial_num = coordinate2serial_num(tmp); if ( serial_num >= 1 && serial_num <= 30 ) { valid_count++; steps[valid_count] = serial_num; } else { cerr << “Not expected to reach here.\n”; } } steps[0] = valid_count; } // 初始化记载所有点的下一步可走点的全局表。 void init_elocution() { for ( int i = 1; i <= 30; i++ ) { next_step(i, elocution[i-1]); } } char track[30]; // 记走过的路径. bool quit_run_horse; // 上文提高的递归函用函数. void run_horse(char start_pos, char step_count) { if ( quit_run_horse ) // 用来快速退出深嵌套递归调用函数. { return; } for ( int i = 0; i < step_count; i++ ) { // 已?经-经-过y这a点?了?. if ( track[i] == start_pos ) { return; } } track[step_count] = start_pos; // 记下新走过的位置 if ( step_count == 29 ) // 最后一步则打印出结果。 { for ( int i = 0; i < sizeof(track); i++ ) { cout << (int)track[i]; if ( i + 1 != sizeof(track) ) { cout << " “; } } cout << endl; quit_run_horse = true; return; } for ( int i = 0; i < elocution[start_pos-1][0]; i++ ) { run_horse(elocution[start_pos-1][i+1], step_count+1); } } int main(int argc, char* argv[]) { init_elocution(); int pos; vector<int> vec; while(true) { cin >> pos; if (pos==-1) { break; } vec.push_back(pos); } for ( int i = 0; i < vec.size(); i++ ) { quit_run_horse = false; run_horse(vec[i], 0); } return 0; }   ...

November 25, 2011 · 4 min · kamus