【题5】骑士游历问题(1)

合集下载

【题5】骑士游历问题(1)

【题5】骑士游历问题(1)

【题5】骑士游历问题(1)设有一个n*m的棋盘(2≤n≤50,2≤m≤50),如图10.2.1。

在棋盘上任一点有一个中国象棋马,图10.2.1马走的规则为:1.马走日字2.马只能向右走。

即如图10.2.2所示:图10.2.2问题:当N,M 输入之后,找出一条从左下角到右上角的路径。

例如:输入N=4,M=4。

对应的路径如图10.2.3所示:图10.2.3输出:路径的格式:(1,1)->(2,3)->(4,4)若不存在路径,则输出"no"题解1.计算跳马方向按题意,中国象棋马共有四个跳动方向图10.2.4我们通过子程序move(x,y,x1,y1,i)计算中国象棋马从(x,y)出发,沿i方向跳至(x1,y1)的过程procedure move(x,y:byte;var x1,y1:byte;i:integer);begincase i of {根据方向计算跳后位置}1:begin x1←x-2;y1←y+1;end;2:begin x1←x-1;y1←y+2;end;3:begin x1←x+1;y1←y+2;end;4:begin x1←x+2;y1←y+1;end;end;{case}end;{move}2.从起始点出发,沿方向序列输出路径设varpath:array[1..1000] of integer;{path[i]—第i步的方向。

初始时path 清零}由(1,1)至(n,m)的路径长度为k。

我们通过调用print(k)过程输出该条路径。

procedure print(k:integer);varx,y,x0,y0:byte;i:integer;beginx←1; y←1;{从(1,1)出发}write(’(’,x,’,’,y,’)’);for i←1 to k do {顺序输出长度为k的跳动路线}beginmove(x,y,x0,y0,path[i]);{第i步由(x,y)跳至(x0,y0)} write(’=>(’,x0,’,’,y0,’)’);x←x0; y←y0; {从(x0,y0)继续往下跳}end;{for}writelnend;{print}3.回溯搜索状态:起跳位置(x,y)和步数k,即准备从(x,y)出发跳第k步;目标:(x,y)为目的地(n,m)。

骑士游历问题(C语言代码)

骑士游历问题(C语言代码)

骑⼠游历问题(C语⾔代码)关于骑⼠游历问题,⼤家可以想到的⽅法是回溯法和贪⼼算法。

回溯法的时间复杂度⽐较⾼,贪⼼算法的时间复杂度就好多了。

骑⼠游历问题问题描述:棋盘⼤⼩是8*8,骑⼠在棋盘任⼀⽅格开始游历。

要求骑⼠游历棋盘的每⼀个⽅格且每个⽅格只游历⼀次。

输出骑⼠的游历路径。

解决思路:dir0、dir1…dir7由⼩到⼤排列,每次选择具有最少出⼝的⽅向,假设为dir0。

如果骑⼠⾛到第n步时,没有出⼝可以选择,同时,骑⼠未完全遍历棋盘,那么骑⼠回溯到上⼀位置((n-1)步),选择dir1⽅向。

骑⼠游历依次进⾏下去。

直⾄⾛到终点或回到原点。

终点代表骑⼠游历完成,原点代表骑⼠游历失败(没有可以游历每个⽅格游历且只游历⼀次的路径)。

这⾥假设当前位置的⼋个⽅向已经按照“具有出⼝”由⼩到⼤排列。

编写程序过程要解决的问题(先考虑简单的问题):⼀、每个位置最多有8个⽅向可以移动分别为:(-2,1) (-1,2) (1,2) (2,1) (2,-1) (1,-2) (-1,-2) (-2,-1);主函数中骑⼠在初始位置时,对个变量进⾏初始化代码:step=1;chessboard[startx][starty]=step;step++;cur_x=startx;cur_y=starty;dir[startx][starty]=max_dir;last_dir=max_dir;考虑到解决骑⼠游历需要⽤到多个函数。

骑⼠前进、后退函数可能⽤到这⼋个⽅向移动的坐标。

故将⼋个⽅向移动的坐标定义为全局变量,“intktmove_x[max_dir],ktmove_y[max_dir];”。

⼆、判断骑⼠应该前进还是回溯:骑⼠在当前位置有可移动的⽅向则前进,反之,回溯到上⼀位置。

⼋⼋棋盘上⾯的每个⽅格最多有⼋个⽅向可以移动。

棋盘数组:“int chessboard[width][width];”,则可以定义⼀个三维数组来判断⽅格某⼀⽅向是否被访问过:“int is_visted[width][width][max_dir]={0};”,初始化为0,表⽰64个⽅格具有的出⼝⽅向(最多有⼋个)未被访问,两个数组同样是全局变量。

Knight_Tour骑士走棋盘【马的Hamilton周游路线问题】

Knight_Tour骑士走棋盘【马的Hamilton周游路线问题】

马的Hamilton周游路线问题-又名骑士走棋盘--------------------------来源:《计算机算法设计与分析(第3版)·王晓东》P44 算法实现题2-4 马的Hamilton周游路线问题--------------------------问题描述:8*8的国际象棋棋盘上的一只马,恰好走过除起点外的其它63个位置各一次,最后回到起点,这条线路成为马的一条Hamilton周游路线。

说明:骑士旅游(Knight tour)在十八世纪初倍受数学家与拼图迷的注意,它什么时候被提出已不可考,骑士的走法为西洋棋的走法,骑士可以由任一个位置出发,它要如何走完[所有的位置?解法:骑士的走法,基本上可以使用递回来解决,但是纯綷的递回在维度大时相当没有效率,一个聪明的解法由J.C. Warnsdorff在1823年提出,简单的说,先将最难的位置走完,接下来的路就宽广了,骑士所要走的下一步,「为下一步再选择时,所能走的步数最少的一步。

」,使用这个方法,在不使用递回的情况下,可以有较高的机率找出走法(找不到走法的机会也是有的)。

------------------------------PS:下面代码在Visual C++ 6.0中编译通过,无警告,无报错!Ps:代码来源《经典算法大全》(电子书PDF)P13------------------------------#include <stdio.h>int board[8][8] = {0};int main(void) {int startx, starty;int i, j;printf("输入起始点:");scanf("%d %d", &startx, &starty);if(travel(startx, starty)) {printf("游历完成!\n");}else {printf("游历失败!\n");}for(i = 0; i < 8; i++) {for(j = 0; j < 8; j++) {printf("%2d ", board[i][j]);}putchar('\n');}return 0;}int travel(int x, int y) {// 对应骑士可走的八个方向int ktmove1[8] = {-2, -1, 1, 2, 2, 1, -1, -2}; int ktmove2[8] = {1, 2, 2, 1, -1, -2, -2, -1}; // 测试下一步的出路int nexti[8] = {0};int nextj[8] = {0};// 记录出路的个数int exists[8] = {0};int i, j, k, m, l;int tmpi, tmpj;int count, min, tmp;i = x;j = y;board[i][j] = 1;for(m = 2; m <= 64; m++) {for(l = 0; l < 8; l++)exists[l] = 0;l = 0;// 试探八个方向for(k = 0; k < 8; k++) {tmpi = i + ktmove1[k];tmpj = j + ktmove2[k];// 如果是边界了,不可走if(tmpi < 0 || tmpj < 0 || tmpi > 7 || tmpj > 7) continue;// 如果这个方向可走,记录下来if(board[tmpi][tmpj] == 0) {nexti[l] = tmpi;nextj[l] = tmpj;// 可走的方向加一个l++;}}count = l;// 如果可走的方向为0个,返回if(count == 0) {return 0;}else if(count == 1) {// 只有一个可走的方向// 所以直接是最少出路的方向min = 0;}else {// 找出下一个位置的出路数for(l = 0; l < count; l++) {for(k = 0; k < 8; k++) {tmpi = nexti[l] + ktmove1[k];tmpj = nextj[l] + ktmove2[k];if(tmpi < 0 || tmpj < 0 ||tmpi > 7 || tmpj > 7) {continue;}if(board[tmpi][tmpj] == 0)exists[l]++;}}tmp = exists[0];min = 0;// 从可走的方向中寻找最少出路的方向for(l = 1; l < count; l++) {if(exists[l] < tmp) {tmp = exists[l];min = l;}}}// 走最少出路的方向i = nexti[min];j = nextj[min];board[i][j] = m;}return 1;}。

骑士游历问题算法的研究

骑士游历问题算法的研究

骑士游历问题算法的研究惠燕;潘煜【摘要】Knight travel problem is a classical mathematical problem. Its thought contributes to the circuit diagram design and image encryption.ff it can be programmed which will have great help in other application fields,it made mathematical model abstraction through the study on the rules of knight travel problems, researched on the direction and the reached conditions of knight travel, knight's moving was abstracted into mathematical expressions, then mapped to the corresponding data structures required in the program,and at last,using JAVA language realized knight travelled graphic demonstration of dynamic processes.%骑士游历问题是一个经典的数学问题.其思想在电路图的设计及图像加密等方面都有帮助,如果能将骑士游历问题算法通过计算机语言程序化将对其在其他领域中的应用有极大帮助.通过研究骑士游历的规则对问题进行数学模型抽象,通过研究骑士游历的方向与可到达情况,将骑士的空间移动抽象成数学表达式,进而映射到程序中所需对应的数据结构形式,最后通过利用JAVA语言得以实现骑士游历问题中骑士游历过程的动态图形演示.【期刊名称】《电子设计工程》【年(卷),期】2011(019)011【总页数】3页(P112-114)【关键词】骑士;游历;欧拉;方向【作者】惠燕;潘煜【作者单位】西安工业大学计算机学院,陕西西安710032;西安工业大学计算机学院,陕西西安710032【正文语种】中文【中图分类】TP311.1骑士游历问题是一个古老而著名的问题,问题的描述是:在8×8格的国际象棋棋盘上,象棋马能否从某个格子出发按照“马跳日”的规则跳遍所有64个格子最后再回到出发的那个格子?国际象棋中的马,英语为knight,恰好又意指中世纪西方世界的“骑士”,因此,这个问题又被称为“骑士游历”问题。

骑士周游详解

骑士周游详解

A Knight's JourneyTime Limit: 1000MS Memory Limit: 65536KTotal Submissions: 14944 Accepted: 4991DescriptionBackgroundThe knight is getting bored of seeing the same black and white squares again and again and has decided to make a journeyaround the world. Whenever a knight moves, it is two squares in one direction and one square perpendicular to this. The world of a knight is the chessboard he is living on. Our knight lives on a chessboard that has a smaller area than a regular 8 * 8 board, but it is still rectangular. Can you help this adventurous knight to make travel plans?ProblemFind a path such that the knight visits every square once. The knight can start and end on any square of the board.InputThe input begins with a positive integer n in the first line. The following lines contain n test cases. Each test case consists of a single line with two positive integers p and q, such that 1 <= p * q <= 26. This represents a p * q chessboard, where p describes how many different square numbers 1, . . . , p exist, q describes how many different square letters exist. These are the first q letters of the Latin alphabet: A, . . .OutputThe output for every scenario begins with a line containing "Scenario #i:", where i is the number of the scenario starting at 1. Then print a single line containing the lexicographically first path that visits all squares of the chessboard with knight moves followed by an empty line. The path should be given on a single line by concatenating the names of the visited squares. Each square name consists of a capital letter followed by a number.If no such path exist, you should output impossible on a single line.Sample Input31 12 34 3Sample OutputScenario #1:A1Scenario #2:impossibleScenario #3:A1B3C1A2B4C2A3B1C3A4B2C4这道简单的题目竟然花了我一个晚上,本来相练习一下用权值来解决这道经典的骑士周游问题,没想到这道题用骑士周游的优化算法竟然超时(用自己的数据跑但是oj上是AC的),oj上跑了813ms 下面是我的code:#include<stdio.h>#include<string.h>#include<stdlib.h>#define lne 27int p,q;int x[lne],y[lne],ans_x[lne],ans_y[lne];int der[8][2]={{-2, -1}, {-1, -2}, {1, -2}, {2, -1}, {2, 1}, {1, 2}, {-1, 2}, {-2, 1}}; bool vis[lne][lne],flag;typedefstruct node{int p,v;}cor;bool canjump(int r,int c){if(r>=0&&r<p&&c>=0&&c<q&&!vis[r][c])returntrue;returnfalse;}int weight(int r,int c){int i,count;for(i=count=0;i<8;i++)if(canjump(r+der[i][0],c+der[i][1]))count++;return count;}int cmp(constvoid *a,constvoid *b){cor *c=(cor *)a;cor *d=(cor *)b;return c->v>d->v?1:-1;}void backtrace(int cur,int r,int c){int i,k,nx,ny;if(cur==p*q){bool fl=false;flag=false;for(i=0;i<p*q;i++){if((ans_y[i]>y[i])||(ans_x[i]>x[i]&&ans_y[i]==y[i])){fl=true;break;}elseif((ans_y[i]<y[i])||(ans_x[i]<x[i]&&ans_y[i]==y[i])) break;}if(fl)for(;i<p*q;i++){ans_x[i]=x[i];ans_y[i]=y[i];}return ;}else{cor ds[8];for(i=k=0;i<8;i++){nx=r+der[i][0];ny=c+der[i][1];if(canjump(nx,ny)){ds[k].v=weight(nx,ny);ds[k++].p=i;}}qsort(ds,k,sizeof(ds[0]),cmp);for(i=0;i<k;i++){nx=r+der[ds[i].p][0];ny=c+der[ds[i].p][1];vis[nx][ny]=true;x[cur]=nx; y[cur]=ny;backtrace(cur+1,nx,ny);vis[nx][ny]=false;}}}void deal(){int i,j;for(i=0;i<p*q;i++)ans_x[i]=ans_y[i]=50;vis[0][0]=true;backtrace(1,0,0);}void output(){int i;if(flag) puts("impossible\n");else{for(i=0;i<p*q;i++)printf("%c%d",ans_y[i]+'A',ans_x[i]+1);puts("\n");}}int main(void){int ncase,i;scanf("%d",&ncase);for(i=1;i<=ncase;i++){memset(vis,false,sizeof(vis));scanf("%d%d",&p,&q);printf("Scenario #%d:\n",i);flag=true;deal();output();}return 0;}然而上面的代码对于8*8的棋盘还是有可行性的,纯粹是数据问题,呵呵后来没办法只能用bfs或者dfs水过,但是由于这道题目只要求求最小字典序的那个结果所以用dfs就可以了,不出意外的话,这道题用dfs做,反而比bfs快,下面是AC的code 16ms :#include<stdio.h>#include<string.h>#include<stdlib.h>#define lne 27int p,q;int x[lne];char y[lne];int der[8][2]={{-1,-2},{1,-2},{-2,-1},{2,-1},{-2,1},{2,1},{-1,2},{1,2}}; bool vis[lne][lne];bool backtrace(int cur,int r,int c){int i,nx,ny;if(cur==p*q-1){x[cur]=r; y[cur]=c+'A';returntrue;}else{for(i=0;i<8;i++){nx=r+der[i][0];ny=c+der[i][1];if(nx>=0&&nx<p&&ny>=0&&ny<q&&!vis[nx][ny]){vis[nx][ny]=true;x[cur]=r; y[cur]=c+'A';if(backtrace(cur+1,nx,ny))returntrue;vis[nx][ny]=false;}}}returnfalse;}int main(void){int ncase,i;scanf("%d",&ncase);for(i=1;i<=ncase;i++){memset(vis,false,sizeof(vis));scanf("%d%d",&p,&q);printf("Scenario #%d:\n",i);vis[0][0]=true;if(backtrace(0,0,0)){for(int j=0;j<p*q;j++)printf("%c%d",y[j],x[j]+1);putchar('\n');}elseputs("impossible");if(i!=ncase) putchar('\n');}return 0;}这是网上用bfs做的code:#include<iostream>usingnamespace std;bool visit[10][10],f;int t,m,i,j,ans[100][2],x,y,p,q;int move[8][2]={{-1,-2},{1,-2},{-2,-1},{2,-1},{-2,1},{2,1},{-1,2},{1,2}};void dg(int p1,int q1,int ans1){visit[p1][q1]=true;ans[ans1][0]=p1,ans[ans1][1]=q1;if (ans1==p*q){f=true;for (i=1;i<=ans1;i++)printf("%c%d",(char)((int)'A'+ans[i][1]-1),ans[i][0]);printf("\n");return;}for (int i1=0;i1<8;i1++){x=p1+move[i1][0],y=q1+move[i1][1];if (x>0&&x<=p&&y>0&&y<=q){if (visit[x][y]==false)dg(x,y,ans1+1);if (f) return;}}visit[p1][q1]=false;return;}int main(){//freopen("2488.in","r",stdin); //freopen("2488.out","w",stdout); scanf("%d",&m);t=0;while(m--){t++;scanf("%d %d",&p,&q);printf("Scenario #%d:\n",t);f=false;memset(visit,0,sizeof(visit));dg(1,1,1);if (!f) printf("impossible\n"); if (m) printf("\n");}return 0;}下面是大牛写的骑士周游的三种方法但是最后的一种贪心是错的/** File: KnightTravel1.cpp* Author: eshow* Date: 2007-09-10* Question:考虑国际象棋棋盘上某个位置的一只马,它是否可能只走63步,正好走过除起点外的其他63个位置各一次?如果有一种这样的走法,则称所走的这条路线为一条马的周游路线。

历届noip提高组复赛试题

历届noip提高组复赛试题

NOI’ 95“同创杯”全国青少年信息学(计算机)奥林匹克竞赛分区联赛复赛试题(高中组)(上机编程,完成时间:210 分钟)<1>编码问题:设有一个数组A:ARRAY[0..N-1] OF INTEGER;数组中存放的元素为0~N-1 之间的整数,且A[i]≠ A[j](当i≠ j时)。

例如: N=6 时,有:此时,数组 A 的编码定义如下:A[0] 的编码为0;A[i] 的编码为:在A[0] ,A[1]∴上面数组 A 的编码为:A= ( 4,3, 0, 5,1, 2),, A[i-1] 中比 A[i] 的值小的个数(B= (0, 0,0,3,1, 2)i=1 ,2,, N-1 )程序要求解决以下问题:①给出数组 A 后,求出其编码。

②给出数组 A 的编码后,求出 A 中的原数据。

<2> 灯的排列问题:设在一排上有 N 个格子( N≤ 20),若在格子中放置有不同颜色的灯,每种灯的个数记为 N 1, N2, N k( k 表示不同颜色灯的个数)。

放灯时要遵守下列规则:①同一种颜色的灯不能分开;②不同颜色的灯之间至少要有一个空位置。

例如: N=8 (格子数)R=2 (红灯数)B=3 (蓝灯数)放置的方法有:R-B 顺序R R B B BR R B B BR R B B BR R B B BR R B B BR R B B BB-R顺序B B B BBBBBBBBBBBBBBR RRRBRRRRRRRR放置的总数为12 种。

数据输入的方式为:NP1(颜色,为一个字母)P2N1(灯的数量)N2Q(结束标记, Q 本身不是灯的颜色)程序要求:求出一种顺序的排列方案及排列总数。

<3> 设有一个四层的积木块,1~ 4 层积木块的数量依次为:5, 6,7, 8如下图所示放置:815851691423414326其中,给出第三层与第四层所标示的数字,并已知第三层的数据是由第四层的数据计算出来的。

骑士巡游问题的回溯法分析

骑士巡游问题的回溯法分析

骑士巡游问题的回溯法分析算法设计与分析课程论文学院:信息工程学院姓名:学号:指导老师:问题描述:骑士巡游(knight'stour)问题就是所指在存有8×8方格的国际象棋棋盘上展开奇特的骑士“l型”(l-shaped)移动的问题。

在国际象棋棋盘8×8方格上的某个格子上置放一个骑士,然后这个骑士就可以以马冲的方式行进,建议这个骑士相继地抵达所有的64个方格,步入每个方格一次且仅步入一次。

问题分析:“l型”移动:骑士的步进方式是按照“l型”移动的,即如下图所示,假设骑士的当前位于粉色格子的位置,那么它的下一步可能出现的合法位置为绿色格子的位置。

如此,我们定义坐标系,棋盘左上角格子为座标原点(0,0),横坐标x轴以右为也已方向,y轴以下为也已方向,当前骑士边线为(x,y),则可能将发生的边线为(x-2,y+1)、(x-1,y+2)、(x+1,y+2)、(x+2,y+1)、(x+2,y-1)、(x+1,y-2)、(x-1,y-2)、(x-2,y-1)。

如此,骑士没进一步都按照此方式步进,直至整个棋盘都被“游走”一遍则完成。

边界情况分析:在骑士“巡游”的过程中难免会游走到棋盘的边缘,那么此时下一步的坐标位置可能超出棋盘边界,此种情况下,需要相关的限定代码予以限制。

此外,因为建议棋盘每个边线必须巡游且只巡游一次,所以当骑士巡游至某一边线时,可能会发生,棋盘没被巡游全然,但不存有合法的之下一步座标点,此种情况下,则牵涉至追溯的问题。

回溯算法的相关介绍:追溯法总述:回溯法(探索与回溯法)是一种选优搜索法,按选优条件向前搜索,以达到目标。

但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。

追溯法的深度优先搜寻策略:追溯法的基本作法就是搜寻,或是一种非政府得井井有的,能避免不必要搜寻的穷举式搜寻法。

骑士周游问题

骑士周游问题

回专题模式回学习阶段模式【题目名称、来源】骑士周游问题(经典题目knight.pas)【问题描述】骑士周游问题如下图所示,国际象棋棋盘上的马一步可以跳向八个方向,问:如果给出一个n*m的棋盘,马从左上角开始跳,是否能够不重复的跳遍所有的格子。

输入:棋盘大小n m列,便利棋盘格子的顺序源程序:【所属专题】【适合学习阶段】【解题思路】问题分析:存储结构:constdirect:array[1..8,1..2] of integer=((-2,1),(-1,2),(2,1),(1,2),(2,-1),(1,-2),(-1,-2),(-2,-1));{马可以跳向八个方向的相对位移,使用常量数组可以将规则统一}Vara:array[1..10,1..10] of integer;{使用数组作为棋盘的存储,如果某一格子没有走过值为0,否则为步数}【测试数据】【源程序】program qishi;{Qi shi zhou you wen ti}constdirect:array[1..8,1..2] of integer=((-2,1),(-1,2),(2,1),(1,2),(2,-1),(1,-2),(-1,-2),(-2,-1));{马可以跳向八个方向的相对位移,使用常量数组可以将规则统一} var n,m,x,y:integer;i,j,count:integer;a:array[1..10,1..10] of integer;procedure tiao(step,x,y:integer);{递归过程实现回溯}var r,i,j,k,l:integer;{r是规则号,i,j是按照r规则跳后的新位置} beginfor r:=1 to 8 do begini:=x+direct[r,1];j:=y+direct[r,2];{求新位置}if (i>=1)and(i<=n)and(j<=m)and(j>=1) then {如果新位置合法}if a[i,j]=0 then begina[i,j]:=step;if step=n*m then begin{如果到达终点则打印}for k:=1 to n do beginfor l:=1 to m do write(a[k,l]:3);writeln;end;close(output);halt;endelse tiao(step+1,i,j);{如果没有到终点,跳下一步}a[i,j]:=0;{回溯}end;end;end;beginassign(input,'qishi.in');reset(input);readln(n,m);{init}assign(output,'qishi.out');rewrite(output);for i:=1 to n dofor j:=1 to m do a[i,j]:=0; {初始化数组}a[1,1]:=1;tiao(2,1,1);writeln('Impossible');close(output);end.。

简单的骑士周游问题的解法

简单的骑士周游问题的解法

"骑士周游问题"是一个经典的图论问题,它要求在一个国际象棋棋盘上,骑士(可以按照L形走动:每次移动两格横向或纵向,再一格横向或纵向)从某一格出发,访问每一格恰好一次后回到起始格子。

解决此问题没有固定的简单算法,但对于较小的棋盘尺寸,比如8x8的棋盘,可以通过穷举搜索的方式来求解。

然而,对于较大的棋盘,由于可能的路径数量呈指数级增长,穷举搜索并不实际。

一种更高效的启发式方法是采用回溯算法或A*搜索等高级搜索算法。

基本思路是设定一个状态空间树,每个节点代表骑士的一种位置状态,然后通过向前探索所有可能的移动方向,并在过程中检查是否重复访问过某个格子,以及是否已经遍历完所有格子。

另外,对于8x8的棋盘,实际上是有解决方案的,并且不止一种,具体的行走路线可以通过计算得出。

这个问题也可以转换成Hamilton回路问题来考虑,但是Hamilton回路问题是NP 完全问题,在一般图上没有多项式时间的确定性算法可以解决,但是对于棋盘这种特殊的图结构,可能存在特定的构造方法或搜索策略来找到解。

骑士问题

骑士问题

骑士问题输入文件:knight.in输出文件:knight.out问题描述:在一个标准8*8的图际象棋棋盘上,棋盘中有些格子可能是有障碍物的。

已知骑士的初始位置和目标位置,你的任务是计算出骑士最少需要多少步可以从初始位置到达目标位置。

有障碍物的格子当然不可以到达。

标准的8*8的国际象棋棋盘中每一个格子可以用唯一的编号确定。

行用1-8这8个数字依次表示,列用‟a‟—…h‟这8个字母依次表示。

例如左下图的骑士所在位置(图中有n 的格子)的编号为“d4”(注意‟d‟和‟4‟之间没有空格)。

我们知道国际象棋中的骑士可以按“L”路线移动(一个方向走2个格子,接着垂直方向走1个格子)。

因此,如左上图中的骑士(位于d4),可以到达位置c2、b3、b5、c6、e6、f5、f3和e2(图中有‟x‟)标记的格子)。

此外,骑士不能移出棋盘。

骑士可以按照移动规则自由地在棋盘上没有障碍物的格子中移动,右上图给出了一个骑士移动的例子。

初始格子用‟n‟标记,目标格子用‟N‟标记,有障碍物的格子用‟b‟标记。

一个可行的移动序列在图中用数字标记出来。

(a1,b3,a5,c6,e5,g4,h2,f1)。

总共需要7步才能完成。

事实上,这也就是最小的步数了。

输入格式:输入文件包括1个或多个测试数据。

每一个测试数据的第一行是一个整数b(-1<=b<=62),表示棋盘中有障碍物的格子数目,当b=-1时,输入文件结束。

第二行含b个不同的有障碍物的格子编号,用空格隔开。

当b=0时,此行为空行。

第三行是骑士的初始格子和目标格子的编号,也是用空格隔开。

初始格子和目标格子是不同的,且都没有障碍物。

输出格式:对于每个数据,输出一行。

格式:Board n: m moves其中n表示数据的序号(从1开始)m表示骑士所用的最小的步数。

如果骑士无法到达目标格子,输出:Board n: not reachable输入样例:10c1 d1 d5 c2 c3 c4 d2 d3 d4 c5a1 f1c1 b32b3 c2a1 b2-1输出样例:Board 1:7 movesBoard 2:1 movesBoard 3:not reachable宽搜(骑士问题)const f:array[1..8,1..2]of integer=((-2,-1),(-1,-2),(1,-2),(2,-1),(2,1),(1,2),(-1,2),(-2,1));type zb=recordi:integer;j:integer;bu:integer;end;var b,i,j,k,answer:integer;pan:array[-1..10,-1..10]of boolean;start,finish:zb;qi:array[1..100000]of zb;can:boolean;procedure zhuan(s:string;var i,j:integer);begini:=ord(s[2])-ord('0');j:=ord(s[1])-ord('a')+1;end;procedure init;var s,sub:string;i,j:integer;beginreadln(s);if s<>'' thenrepeatsub:=copy(s,1,2);zhuan(sub,i,j);pan[i,j]:=false;delete(s,1,3);until s='';readln(s);sub:=copy(s,1,2);zhuan(sub,start.i,start.j);sub:=copy(s,4,2);zhuan(sub,finish.i,finish.j);end;function ok(i,j:integer):boolean;beginif (i>0) and (i<9) and (j>0) and (j<9) and pan[i,j] then ok:=true else ok:=false; end;procedure work;var p,q,i:integer;qs,kz:zb;pd:boolean;beginp:=0;q:=1;qi[1].i:=start.i;qi[1].j:=start.j;qi[1].bu:=0;can:=true;pd:=false;repeatinc(p);qs:=qi[p];for i:=1 to 8 dobeginkz.i:=qs.i+f[i,1];kz.j:=qs.j+f[i,2];if ok(kz.i,kz.j) thenbeginpan[kz.i,kz.j]:=false;inc(q);qi[q].i:=kz.i;qi[q].j:=kz.j;qi[q].bu:=qi[p].bu+1;if (kz.i=finish.i) and (kz.j=finish.j) thenbeginpd:=true;answer:=qi[q].bu;end;end;end;until (p=q) or (pd);if p=q then can:=false;end;procedure print;beginif can then writeln(answer,' moves') else writeln('not reachable'); end;beginassign(input,'knight.in'); reset(input);assign(output,'knight.out'); rewrite(output);k:=0;repeatreadln(b);inc(k);if b<>-1 thenbeginwrite('Board ',k,': ');for i:=1 to 8 dofor j:=1 to 8 do pan[i,j]:=true; init;work;print;end;until b=-1;close(input);close(output);end.。

骑自行车旅行记测试题及答案

骑自行车旅行记测试题及答案

骑自行车旅行记测试题及答案
为了检验大家对《骑自行车旅行记》一书的理解和掌握程度,我们特此准备了以下测试题。

请根据自己的知识储备和阅读体验,认真作答。

一、选择题
请从A、B、C、D四个选项中,选出最符合题意的答案。

1. 《骑自行车旅行记》的作者是哪位作家?
A. 马克·吐温
B. 简·奥斯汀
C. 乔治·奥威尔
D. 村上春树
答案:A
2. 书中主人公骑自行车旅行的主要目的是什么?
A. 寻找心灵的归宿
B. 体验不同的美食文化
C. 完成一次冒险之旅
D. 探访世界各地的名胜古迹
答案:A
3. 在旅行过程中,主人公遇到了哪些有趣的人和事?
A. 与当地居民一起参加传统节日庆典
B. 在荒野中邂逅神秘的骑行者
C. 结识了一群志同道合的骑行者
D. 以上都是
答案:D
二、简答题
请根据自己对本书的理解,简要回答以下问题。

1. 请简述本书的主人公在旅行过程中,如何逐渐找到心灵的归宿。

答案:(答案请自行阐述)
2. 请谈谈你对本书中描述的自行车旅行文化的看法。

答案:(答案请自行阐述)
三、论述题
请结合本书的内容,论述一下你认为自行车旅行对个人成长的意义。

答案:(答案请自行阐述)
希望大家在完成测试题的过程中,能够进一步深化对《骑自行车旅行记》的理解和感悟。

祝大家阅读愉快!。

骑士巡游问题[回溯法]

骑士巡游问题[回溯法]

骑⼠巡游问题[回溯法]问题: 在 n × n ⽅格的国际象棋棋盘上,马(也称为骑⼠Knight)从任意指定的⽅格出发,以跳马规则(横⼀步竖两步或横两步竖⼀步),周游棋盘的每⼀个格⼦,要求每个格⼦只能跳过⼀次。

思路: 搜索部分就是普通的回溯 void KnightPatrol(int n, int count, step steps[], int map[][8]){//n表⽰棋盘规模,count表⽰骑⼠已经⾛过的步数,steps记录骑⼠巡游过的点,map⽤来标记地图上每个点有没被⾛过if (count == n*n){//如果骑⼠巡游过了所有的点display(steps, n);}for (int i = N; i <= NW; i++){//对每个⽅向遍历step then = overlook(steps[count], i);//向i⽅向眺望⼀下bool lonely = false;if (count % 2 == 0){lonely = hasLonelyPoint(map, n);}if (isInside(n, then) && !isOverlap(map, then) && !lonely){//如果骑⼠下⼀步没有跑到地图外⾯,且没有⾛到刚才⾛过的地⽅//并且地图中没有⾛不到的点patrol(steps, count, then, map);KnightPatrol(n, count + 1, steps, map);map[steps[count + 1].x][steps[count + 1].y] = 0;}}}但是我这⾥设计了⼀个剪枝函数,具体思路就是每⾛⼀步,就判断下地图中是否有永远不能被⾛到的点就是因为这个棒棒哒剪枝函数,运⾏速度提⾼了不知道多少bool hasLonelyPoint(int map[][8], int n){//判断地图中是否有孤⽴的点,即怎么都⾛不到的点step point1, point2;for (int i = 1; i <= n; i++){for (int j = 1, count = 0; j <= n; j++){if (map[i][j] == 0){point1.x = i;point1.y = j;int count = 0;for (int k = N; k <= NW; k++){point2 = overlook(point1, k);if (!isInside(n, point2)) count++;//point1 周围的8个点中有点在地图外if (map[point2.x][point2.y] == 1) count++;//point1 周围的8个点中有点被踩过}if (count >= 8) return true;//如果8个⽅向全都不⾏,说明这个点永远都⽆法被⾛到了}}}return false;}。

骑士问题

骑士问题

楼主小大?个性首页 | 邮箱骑士游历问题_动规解法设有一个m×n的棋盘(2≤m≤50,2≤n≤50),在棋盘上任一点有一个中国象棋“马”,马走的规则为:马走日字;马只能向右走。

当m,n给出后,同时给出马起始的位置和终点的位置,试找出从起点到终点所有路径的数目。

输入:??? m,n,x1,y1,x2,y2 (分别表示m,n、起点坐标和终点坐标)输出:??? 路径数目(若不存在,则输出0)【分析】?? 本题可以使用深度搜索发求解,但是效率很低,当路径很多时,不可能在短时间内出解。

可以采用动态规划的设计思想。

??? 从(x1,y1)位置出发,按照由左到右的顺序定义阶段的方向。

位于(x2,y2)的左方且可达(x2,y2)的跳马位置集合都是(x2,y2)的子问题,起点至(x2,y2)的路径数实际上等于起点至这些位置集的路径数之和。

可以按照阶段的顺序依次计算每一个阶段每个点的路径数目。

??? 阶段i:中国象棋马当前的列位置(x1≤i≤x2)??? 状态j:中国象棋马在i列的行位置(1≤i≤m)??? 状态转移方程map[i,j]:起点(x1,y1)至(i,j)的路径数目??? 具体算法如下:fillchar(map,sizeof(map),0);map[x1,y1]←1;for i←x1+1 to x2 do? for j←1 to m do???? map[i,j]←map[i-1,j-2]+map[i-1,j+2]+map[i-2,j-1]+map[i-2,j+1];writeln(map[x2,y2]);【参考程序】program qishiyouli;constmaxm=50;maxn=50;varm,n,x1,y1,x2,y2:integer;i,j,k,x,y:integer;map:array[-2..maxm+2,-2..maxn+2] of extended;beginfillchar(map,sizeof(map),0);readln(m,n,x1,y1,x2,y2);map[x1,y1]:=1;for i:=x1+1 to x2 dofor j:=1 to m domap[i,j]:=map[i-1,j-2]+map[i-1,j+2]+map[i-2,j-1]+map[i-2,j+1]; writeln(map[x2,y2]:0:0);end.。

骑士巡游问题

骑士巡游问题

骑⼠巡游问题问题概述骑⼠巡游问题对国际象棋爱好者来说是较有意思的难题之⼀。

这个问题是:称为骑⼠的棋⼦在⼀个空的棋盘上⾏进,能否在64个⽅格棋盘上的每个⽅格都⾛⼀次且只⾛⼀次。

在国际象棋中,骑⼠的移动路线是L形的(在⼀个⽅向上⾛两格,在垂直⽅向上⾛⼀格)。

因此在⼀个空棋盘中间的⽅格上,其实可以有8种不同的移动⽅式(从0到7编号),如下图所⽰:可达性试探法算法思想根据每个⽅格的可到达程度将它们分类,然后总是把骑⼠移动到最难到达的那个⽅格(即可达性数字最⼩的⽅格,贪⼼算法的感觉)。

我们给⼀个⼆维array对象access填上数,这些数表⽰每个⽅格周围有多少个可到达的⽅格。

在⼀个空棋盘上,每个中⼼⽅格定为8,每个⾓落定为2,其他的⽅格为3、4或6,如下所⽰:在任何时候,骑⼠都应该移动到具有最低可达数的⽅格。

如果满⾜此条件的⽅格不⽌⼀个,骑⼠可以选择移动到其中的任何⼀个⽅格。

因此,骑⼠巡游可以从任何⼀个⾓落开始。

需要注意的是:随着骑⼠在棋盘上的移动,越来越多的⽅格被占⽤,因此应该随之减少可达数。

这样,在巡游的任何时刻,每个有效⽅格的可达数与该⽅格可到达的确切⽅格数保持相等。

C++实现#include <iostream>#include <iomanip>#include <ctime>using namespace std;const int SIZE = 8;// 检测当前选择的位置是否有效bool vaildWay(int col, int row, int board[][SIZE]) {return (col >= 0 && col < SIZE && row >= 0&& row < SIZE && !board[row][col]);}int main() {int board[SIZE][SIZE] = { 0 }; // 初始化棋盘数组int access[SIZE][SIZE] = { 2, 3, 4, 4, 4, 4, 3, 2,3, 4, 6, 6, 6, 6, 4, 3,4, 6, 8, 8, 8, 8, 6, 4,4, 6, 8, 8, 8, 8, 6, 4,4, 6, 8, 8, 8, 8, 6, 4,4, 6, 8, 8, 8, 8, 6, 4,3, 4, 6, 6, 6, 6, 4, 3,2, 3, 4, 4, 4, 4, 3, 2 }; // 可达性数组int horizontal[SIZE] = { 2, 1, -1, -2, -2, -1, 1, 2 }; // ⽔平位移int vertical[SIZE] = { -1, -2, -2, -1, 1, 2, 2, 1 }; // 垂直位移int currentCol, currentRow; // 当前位置int testCol, testRow; // 测试位置int moveSteps = 0; // 移动步伐srand(time(0));currentCol = rand() % 8; // 随机选择起始位置currentRow = rand() % 8;board[currentRow][currentCol] = ++moveSteps; // 标记起始位置bool done = false;while (!done) {int miniWay = 9; // 挑选最⼩的可达性位置int direction = -1; // 记录⽅向for (int i = 0; i < SIZE; ++i) { // 扫描8个⽅向testCol = currentCol + horizontal[i];testRow = currentRow + vertical[i];if (vaildWay(testCol, testRow, board)) {if (access[testRow][testCol] < miniWay) {miniWay = access[testRow][testCol];direction = i;}--access[testRow][testCol]; // 更新可达性数组}}if (direction == -1) // 如果没有合适的⽅向done = true;else { // 更新当前位置currentCol += horizontal[direction];currentRow += vertical[direction];board[currentRow][currentCol] = ++moveSteps;}}if (moveSteps == 64) // 如果遍历到所有的⽅格位置cout << " successful!!\n\n";elsecout << " failed\n\n";for (int i = 0; i < SIZE; ++i) { // 输出棋盘数据for (int j = 0; j < SIZE; ++j)cout << setw(3) << board[i][j];cout << endl;}return 0;}暴⼒⽅法算法思想所谓暴⼒⽅法,就是不断试错,不断的使⽤随机数进⾏测试,直到完成需要的⽬标或者达到⽬的次数为⽌。

骑士巡游问题

骑士巡游问题

骑⼠巡游问题国际象棋为许多令⼈着迷的娱乐提供了固定的框架,这些框架独⽴于游戏本⾝。

其中很多都是基于奇异的骑⼠“L型”(L-shaped)移动。

⼀个经典的例⼦就是骑⼠巡游(knight's tour)问题。

编写程序求解骑⼠巡游问题:在n⾏m列的棋盘上,输出⼀位骑⼠(按象棋中“马⾛⽇”的⾏⾛法)从(1,1)开始,遍历棋盘的顺序。

骑⼠的⼋种跳法⽤以下常量数组表⽰(表⽰每跳⼀步在⾏和列上的变化量):constdx:array [1..8] of integer=(-2,-1,1,2,2,1,-1,-2);dy:array [1..8] of integer=(1,2,2,1,-1,-2,-2,-1);输⼊输⼊两个数n,m表⽰棋盘为n⾏m列。

输出输出⼀个n⾏m列的矩阵(每个数场宽为3),第I⾏,第J列的数C,表⽰骑⼠在第C步时位于第I⾏,第J列。

样例输⼊5 5样例输出1 20 17 12 316 11 2 7 1821 24 19 4 1310 15 6 23 825 22 9 14 5constdx:array [1..8] of integer=(-2,-1,1,2,2,1,-1,-2);dy:array [1..8] of integer=(1,2,2,1,-1,-2,-2,-1);vara:array[1..100,1..100] of integer;n,m,sum:longint;procedure prt;var i,j:integer;beginfor i:=1to n dobeginfor j:=1to m dowrite(a[i,j],'');writeln;end;inc(sum); writeln('==== ',sum,' ====='); {如只要⼀个解,将此⾏改为halt}end;procedure work(x,y,dep:longint);var i:integer;begina[x,y]:=dep;if dep=n*m then prtelse beginfor i:=1to8doif (x+dx[i]>0)and(x+dx[i]<n+1)and(y+dy[i]>0)and(y+dy[i]<m+1)then if (a[x+dx[i],y+dy[i]]=0) thenbeginwork(x+dx[i],y+dy[i],dep+1);a[x+dx[i],y+dy[i]]:=0;end;end;end;beginreadln(m,n);work(1,1,1);end.。

智力测试题骑士(3篇)

智力测试题骑士(3篇)

第1篇一、前言自古以来,骑士一直被视为英勇、忠诚、智慧的代表。

为了检验各位勇士的智慧,特此推出一场以骑士为主题的智力测试。

以下是试题,请各位勇士仔细阅读,并认真作答。

二、试题1. 单选题(1)以下哪位不是中世纪欧洲著名的骑士?A. 罗宾汉B. 亚瑟王C. 勇敢的心D. 阿尔萨斯(2)以下哪项不是骑士的荣誉?A. 忠诚B. 勇敢C. 美貌D. 财富(3)以下哪个国家不是中世纪欧洲的骑士国家?A. 法国B. 英国C. 德国D. 日本2. 多选题(1)以下哪些是骑士阶层的职责?A. 保护弱者B. 打击邪恶C. 建设家园D. 研究科学(2)以下哪些是骑士阶层的道德准则?A. 忠诚B. 勇敢C. 谦虚D. 懒惰3. 判断题(1)骑士阶层起源于古希腊。

()(2)骑士阶层的最高级别是爵士。

()(3)骑士在战场上只能使用长剑。

()(4)骑士阶层的女性被称为女骑士。

()4. 简答题(1)简述骑士阶层的起源和发展。

(2)骑士阶层的道德准则有哪些?(3)骑士在现代社会有何意义?5. 论述题(1)结合实际,谈谈你对骑士精神的看法。

(2)在现代社会,如何传承和发扬骑士精神?三、答案1. 单选题(1)D(2)C(3)D2. 多选题(1)A、B、C(2)A、B、C3. 判断题(1)×(2)√(3)×(4)√4. 简答题(1)骑士阶层的起源可以追溯到古希腊,后来传入欧洲。

在中世纪,骑士阶层逐渐发展壮大,成为欧洲社会的中坚力量。

骑士阶层主要负责保护弱者、打击邪恶、建设家园等职责。

(2)骑士阶层的道德准则包括:忠诚、勇敢、谦虚、正义、仁爱等。

(3)在现代社会,骑士精神具有重要的意义。

它代表着勇敢、忠诚、正义等美好品质,对人们的成长具有积极的促进作用。

5. 论述题(1)骑士精神是一种崇高的精神品质,它代表着勇敢、忠诚、正义等美好品质。

在现代社会,骑士精神具有以下意义:① 培养人们的勇气和担当意识,面对困难和挑战时,勇敢地迎难而上。

骑士游历问题 纯数学方法

骑士游历问题 纯数学方法

poj2243 骑士游历问题的纯数学方法/problem?id=2243下面稍微翻译一下:描述:给你一个8*8的棋盘,骑士的开始位置,结束位置,让你求得骑士从开始位置开始揍到结束位置需要最小的步数是多少?(注意,骑士走日字)输入:输入包含多组数据,每一行都是一组开始位置和结束位置,位置由两个字符组成,一个是小写字母(a-h),一个是数字(1-8),起始位置结束位置由一个空格隔开.输出:输出从起始位置到结束位置,骑士所要走过的最小的步数.按照样例的格式来。

输入样例:e2 e4a1 b2b2 c3a1 h8a1 h7h8 a1b1 c3f6 f6输出样例:To get from e2 to e4 takes 2 knight moves.To get from a1 to b2 takes 4 knight moves.To get from b2 to c3 takes 2 knight moves.To get from a1 to h8 takes 6 knight moves.To get from a1 to h7 takes 5 knight moves.To get from h8 to a1 takes 6 knight moves.To get from b1 to c3 takes 1 knight moves.To get from f6 to f6 takes 0 knight moves.-------------------------------------------------------------------------------------------------------------一般网上见到的都是dp或者bfs方法。

但是,对于n稍微大一点,比如80*80,100*100的方格,就很麻烦了。

今天中午,我终于想出来了一个数学方法。

是这样的:首先,对于两个点,只用考虑其横纵坐标的差值。

骑士游历问题

骑士游历问题

for(k=0;k<n;k++)
{
p->childptr[k]=(CTree *)malloc(sizeof(CTree));
for(i=0;i<n;i++)
for(j=0;j<m;j++)
p->childptr[k]->a[i][j]=p->a[i][j];
p->childptr[k]->tag=1;
else
/*上一列下了棋子且该列为第m列*/
for(k=0;k<n;k++)
{
p->childptr[k]=(CTree *)malloc(sizeof(CTree));
for(i=0;i<n;i++)
for(j=0;j<m;j++)
p->childptr[k]->a[i][j]=p->a[i][j];
p->childptr[k]->tag=1;
p->childptr[k]->a[k][y]=1;
if(k==x-3||k==x+1)
Trial(p->childptr[k],k+1,y+1);
else free(p->childptr[k]);
}
}
}
else if(p->tag==0)
/*上一列没有下棋子*/
☆ 依照分析,建立状态树如下:
棋盘状态树
正确路径
说明:
1. 状态树中每一个结点除了图中表示出的二维表外,还包含n 个指向孩子结点的指针域和一个整型标志变量tag,当树的i层 结点的tag为1时,表示该结点在第y1+i-1列不下棋子,tag为0 时则表示在该列某行下一个棋子。 2.在m-1列时,要继续前进时,只有一种走法,就是在第m列 寻找正确路径,不能在m列不下棋子,因此,m层的结点tag必 须等于1。 3.如果在某列下了棋子,在下一列可以有两种选择,下棋子 和不下棋子,在树中表现为分配n+1个结点,其中一个为不 下棋子即tag=0,其它n个表示分别在下列不同的行放入棋子; 如果在该列不下棋子,则下一行必须下棋子,否则会遗漏可 能路径,即有n个孩子,且孩子的tag均为1。
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

【题5】骑士游历问题(1)
设有一个n*m的棋盘(2≤n≤50,2≤m≤50),如图10.2.1。

在棋盘上任一点有一个中国象棋马,
图10.2.1
马走的规则为:
1.马走日字
2.马只能向右走。

即如图10.2.2所示:
图10.2.2
问题:当N,M 输入之后,找出一条从左下角到右上角的路径。

例如:输入N=4,M=4。

对应的路径如图10.2.3所示:
图10.2.3
输出:路径的格式:(1,1)->(2,3)->(4,4)
若不存在路径,则输出"no"
题解
1.计算跳马方向
按题意,中国象棋马共有四个跳动方向
图10.2.4
我们通过子程序move(x,y,x1,y1,i)计算中国象棋马从(x,y)出发,沿i方向跳至(x1,y1)的过程
procedure move(x,y:byte;var x1,y1:byte;i:integer);
begin
case i of {根据方向计算跳后位置}
1:begin x1←x-2;y1←y+1;end;
2:begin x1←x-1;y1←y+2;end;
3:begin x1←x+1;y1←y+2;end;
4:begin x1←x+2;y1←y+1;end;
end;{case}
end;{move}
2.从起始点出发,沿方向序列输出路径

var
path:array[1..1000] of integer;{path[i]—第i步的方向。

初始时path 清零}
由(1,1)至(n,m)的路径长度为k。

我们通过调用print(k)过程输出该条路径。

procedure print(k:integer);
var
x,y,x0,y0:byte;
i:integer;
begin
x←1; y←1;{从(1,1)出发}
write(’(’,x,’,’,y,’)’);
for i←1 to k do {顺序输出长度为k的跳动路线}
begin
move(x,y,x0,y0,path[i]);{第i步由(x,y)跳至(x0,y0)} write(’=>(’,x0,’,’,y0,’)’);
x←x0; y←y0; {从(x0,y0)继续往下跳}
end;{for}
writeln
end;{print}
3.回溯搜索
状态:起跳位置(x,y)和步数k,即准备从(x,y)出发跳第k步;
目标:(x,y)为目的地(n,m)。

若满足条件,则输出长度为k-1的路径并成功退出;
搜索范围:四个跳动方向,即1≤i≤4。

中国象棋马沿i方向跳至(x1,y1);
约束条件:(x1,y1)在界内。

若满足条件,则记下第k步的方向i,并从(x1,y1)出发递归第k+1步;
procedure search(k:integer;x,y:byte);
var
i:integer;
x1,y1:byte;
begin
if (x=n) and (y=m) {若(x,y)为目的地,则输出长度为k-1的路径并成功退出}
then begin
print(k-1); halt;
end;
for i←1 to 4 do {搜索4个方向}
begin
move(x,y,x1,y1,i); { 中国象棋马从(x,y)出发,沿i方向跳至(x1,y1)} if (x1 in [1..n]) and (y1 in [y+1..m]){若(x1,y1)在右方界内,则记下第k步的方向i,并从(x1,y1)出发递归第k+1步}
then begin path[k]←i; search(k+1,x1,y1);end;{then}
end{for}
end;{ search }
显然,递归调用search(1,1,1)后可得出由(1,1)至(n,m)的一条路径。

相关文档
最新文档