第七次实验 马踏棋盘问题
马踏棋盘
马踏棋盘学院专业学号学生姓名指导教师年月日摘要:国际象棋想必大家都玩过,但你有没有想过,让一个“马”遍历国际象棋8*8的棋盘,有没有可能?如果有可能,在给定起点的情况下,有多少种可能?下面,我们将用计算机来模拟“马”对棋盘的遍历.关键字:回溯算法贪心算法遍历正文:已知国际象棋为8×8棋盘,共64个格,规则中,马按照如图所示规则移动。
将马放在任意方格中,令马遍历每个方格一次且仅一次,编制非递归程序,将数字1,2, (64)照马的行走路线依次填入一个8×8的方阵,并输出结果。
通过结合图示,我们不难发现,当马的起始位置(i,j)确定的时候,可以走到下列8个位置之一:(i-2,j+1)、(i-1,j+2)、(i+1,j+2)、(i+2,j+1)、(i+2,j-1)、(i+1,j-2)、(i-1,j-2)、(i-2,j-1)但是,如果(i,j)靠近棋盘的边缘,上述有些位置可能超出棋盘范围,成为不可达的位置。
8个可能位置可以用一维数组Htry1[0…7]和HTry2[0..7]来表示:Htry1:0 1 2 3 4 5 6 7-2 -1 1 2 2 1 -1 -2 Htry2:0 1 2 3 4 5 6 71 2 2 1 -1 -2 -2 -1所以位于(i,j)的马可以走到新位置是在棋盘范围内的(i+ Htry1[h],j+Htry2[h]),其中h的取值是0~7.整个问题,我们可以用两种算法来解决,既“回溯算法”与“贪心算法”我们先来看回溯算法:搜索空间是整个棋盘上的8*8个点.约束条件是不出边界且每个点只能经过一次.搜索过程是从一点(i,j)出发,按深度有限的原则,从8个方向中尝试一个可以走的点,直到走过棋盘上所有的点.当没有点可达且没有遍历完棋盘时,就要撤销该点,从该点上一点开始找出另外的一个可达点,直到遍历完整个棋盘我们接着看程序的需求分析:1.输入的形式和输入值的范围;分开输入马的初始行坐标X和列坐标Y,X和Y的范围都是[0,7]。
马跳棋盘问题
用贪婪算法优化马踏棋盘问题一、问题阐述将马放到国际象棋的8*8棋盘board上的某个方格中,马按走棋规则进行移动,要求每个方格进入且只进入一次,走遍棋盘上的64个方格,将数字1,2,3…,64依次填入一个8*8的方阵,找出一种可行的方案,并用贪婪算法进行优化。
0 1 2 3 4 5 6 7如图所示,当马在棋盘位置(4,3)时,它可以有1,2,3,4,5,6,7,8个位置可跳二、解题思路1.需求分析棋盘可以看做一个矩阵,当马位于棋盘上某一位置时,它就有一个唯一的坐标,那么根据国际象棋的规则,它有8个位置可以跳,这8个位置的坐标是和当前马的坐标是有联系的,例如马的坐标是(x,y),那么它的下一跳的位置可以是(x-1,y-2)。
当然坐标不能越界。
马所在的当前位置标为1,它的下一跳的位置标为2,在下一跳的位置标为3,依次类推,如果马走完棋盘,那么最后在棋盘上标的位置是64。
2.解决方案(1)回溯法我们可以采用回溯法求解,当马在当前位置时,我们将它下一跳的所有位置保存,然后从中选择一个位置作为当前位置在跳,递归下去,如果跳不下去,回溯。
这有点类似图的深度搜索。
(2)贪婪法贪婪算法是指,在对问题求解时,总是做出在当前看来是最好的选择。
也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。
那么我们在回溯法的基础上,用贪婪算法进行优化,在选择下一跳的位置时,总是选择出口少的那个位置,这里出口少是指这个位置的下一跳位置个数少。
这是一种局部调整最优的做法,如果优先选择出口多的子结点,那出口少的子结点就会越来越多,很可能出现‘死’结点,这样对下面的搜索纯粹是徒劳,这样会浪费很多无用的时间,反过来如果每次都优先选择出口少的结点跳,那出口少的结点就会越来越少,这样跳成功的机会就更大一些。
三、编写代码#include <iostream>#include <fstream>#include <ctime>#include <cstdlib>#include <queue>#include <vector>using namespace std;class Point{protected:int x;int y;public:Point(int X=0,int Y=0):x(X),y(Y){}Point(const Point& P){x=P.x;y=P.y;}Point& operator=(const Point& P){x=P.x;y=P.y;return *this;}int getX() const{return x;}int getY() const{return y;}void setX(int X){x=X;}void setY(int Y){y=Y;}};class PointX:public Point{private:int cnt_NextJump; //当马以当前位置为基准,下一跳位置的个数public:PointX(int X=0,int Y=0,int cnt=0):Point(X,Y){}PointX(const PointX& p){x=p.x;y=p.y;cnt_NextJump=t_NextJump;}PointX& operator=(const PointX& p){x=p.x;y=p.y;cnt_NextJump=t_NextJump;return *this;}int getCnt() const{return cnt_NextJump;}void setCnt(int cnt){cnt_NextJump=cnt;}};const int N=8;int offsetX[N]={-1,1,-1,1,-2,-2,2,2}; //相对于当前点马的下一落脚点x 的偏移量int offsetY[N]={-2,-2,2,2,-1,1,-1,1}; //相对于当前点马的下一落脚点y 的偏移量ofstream file1; //文件输出流class SearchPath //寻径类{protected:int chessboard[N][N]; //棋盘Point startPoint; //起始点bool find; //find=false表示没有找到路径int RecursiveDepth; //递归的深度bool JudgeNextJumpPoint(int x,int y) //判断下一跳的位置是否合法{//其中chessboard[x][y]==0表示马可以跳到(x,y)的位置if(x<N && x>=0 && y<N && y>=0 && chessboard[x][y]==0) return true;else return false;}void Solution(Point p,int count){if(find) return;RecursiveDepth++;int x,y;x=p.getX();y=p.getY();chessboard[x][y]=count;if(count>=N*N){find=true;Success(); //输出解}int i;queue<Point>Q;for(i=0;i<N;i++){Point candidatePoint(x+offsetX[i],y+offsetY[i]); //求出候选的点if(JudgeNextJumpPoint(candidatePoint.getX(),candidatePoint.getY()) ==false) continue; //判断候选点的合法性Q.push(candidatePoint); //如果合法入队列}while(Q.empty()==false) //当队列不空时{Point next=Q.front(); //取出队头元素Q.pop();Solution(next,count+1);chessboard[x][y]=0;//当Solution返回到此时说明上一步求出的候选点没有子候选点,所以讲此位置重新置为0}}void Success(){int i,j;for(i=0;i<N;i++){for(j=0;j<N;j++) file1<<chessboard[i][j]<<" ";file1<<endl;}}public:SearchPath(const Point& s){int i,j;for(i=0;i<N;i++) //初始化棋盘{for(j=0;j<N;j++) chessboard[i][j]=0;}if(JudgeNextJumpPoint(s.getX(),s.getY())==false){cerr<<"输入点的位置非法!"<<endl;exit(1);}RecursiveDepth=0;find=false;startPoint=s;}void Solution(){int count=1;Solution(startPoint,count);}int getRecursiveDepth() const{return RecursiveDepth;}};ofstream file2;class Greedy_SearchPath:public SearchPath {private:void Success(){int i,j;for(i=0;i<N;i++){for(j=0;j<N;j++) file2<<chessboard[i][j]<<" ";file2<<endl;}}void SetNextJumpCnt(PointX& p) //设置点p位置下一跳的个数{int cnt=0;int i;int x=p.getX();int y=p.getY();for(i=0;i<N;i++){PointX candidatePoint(x+offsetX[i],y+offsetY[i],0); //求出候选的点if(JudgeNextJumpPoint(candidatePoint.getX(),candidatePoint.getY()) ==false) continue; //判断候选点的合法性cnt++;}p.setCnt(cnt);}void Solution(PointX p,int count){if(find) return;RecursiveDepth++;int x,y;x=p.getX();y=p.getY();chessboard[x][y]=count;if(count>=N*N){find=true;Success(); //输出解}int i;vector<PointX>v; //用向量去存储候选点for(i=0;i<N;i++){PointX candidatePoint(x+offsetX[i],y+offsetY[i],0); //求出候选的点if(JudgeNextJumpPoint(candidatePoint.getX(),candidatePoint.getY()) ==false) continue; //判断候选点的合法性SetNextJumpCnt(candidatePoint);v.push_back(candidatePoint); //如果合法加入向量}vector<PointX>::iterator it,min;int cnt=N+1;while(v.empty()==false) //当向量不空时{for(it=v.begin(),min=it;it!=v.end();it++) //查找下一跳个数最少的位置{if(it->getCnt()<cnt){cnt=it->getCnt();min=it;}}PointX next=*min; //取出元素v.erase(min);Solution(next,count+1);chessboard[x][y]=0;//当Solution返回到此时说明上一步求出的候选点没有子候选点,所以讲此位置重新置为0}}public:Greedy_SearchPath(const Point& s):SearchPath(s){}void Solution(){int count=1;PointX p(startPoint.getX(),startPoint.getY());Solution(p,count);}};void main(){int n=20;int i;int x,y;srand(unsigned(time(NULL)));file1.open("e:\\log1.txt");if(!file1) return;file2.open("e:\\log2.txt");if(!file2) return;for(i=0;i<n;i++){x=rand()%N;y=rand()%N;Point p(x,y);SearchPath s(p);Greedy_SearchPath ss(p);s.Solution();ss.Solution();file1<<s.getRecursiveDepth()<<endl;file2<<ss.getRecursiveDepth()<<endl;}}四、测试数据我们随机选择20个位置作为测试,分别用回溯法和贪婪法记录每次成功方案的递归深度,递归深度越少,性能越佳。
数据结构实验报告马踏棋盘
目录1 课程设计的目的 (x)2 需求分析 (x)3 课程设计报告内容 (x)1、概要设计 (x)2、详细设计 (x)3、调试分析 (x)4、用户手册 (x)5、测试结果 (x)6、程序清单 (x)4 小结 (x)5 参考文献 (x)2011年5月23日1、课程设计的目的(1)熟练使用栈和队列解决实际问题;(2)了解并掌握数据结构与算法的设计方法,具备初步的独立分析和设计能力;(3)初步掌握软件开发过程的问题分析、系统设计、程序编码、测试等基本方法和技能;(4)提高综合运用所学的理论知识和方法独立分析和解决问题的能力;2、需求分析*问题描述:将马随机放在国际象棋的8X8棋盘Bo阿rd[0..7,0..7]的某个方格中,马按走棋规则进行移动。
要求每个方格上只进入一次,走遍棋盘上全部64个方格。
编制非递归程序,求出马的行走路线,并按求出的行走路线,将数字1,2,…,64依次填入8X8的方阵输出之。
*测试数据:由读者指定,可自行指定一个马的初始位置。
*实现提示:每次在多个可走位置中选择一个进行试探,其余未曾试探过的可走位置必须用适当结构妥善管理,以备试探失败时的“回溯”(悔棋)使用。
并探讨每次选择位置的“最佳策略”,以减少回溯的次数。
3、课程设计报告内容根据分析先建了2个结构体struct PosType //马的坐标位置类型{int m_row; //行值int m_col; //列值};struct DataType //栈的元素类型{PosType seat; //马在棋盘中的“坐标位置”int di; //换方向的次数};chess::chess()bool chess::chessPath(PosType start) //在棋盘中进行试探寻找下一步位置并同时记录位置,以及涉及到的入栈出栈void chess::Print() //打印马走的路径PosType chess::NextPos(PosType a,int di)//根据当前点的位置a和移动方向di,试探下一位置4、总结一、这次课程设计的心得体会通过实践我的收获如下:1、巩固和加深了对数据结构的理解,提高综合运用本课程所学知识的能力。
马踏棋盘实习报告
一、实习背景马踏棋盘问题是一个经典的算法问题,也是数据结构课程中的一个重要实验。
通过对马踏棋盘问题的研究和实现,可以加深对栈和队列这两种抽象数据类型的理解,提高算法设计能力和编程能力。
本次实习旨在通过编程实现马踏棋盘问题,并分析其算法的复杂度和优化策略。
二、实习目的1. 理解马踏棋盘问题的背景和意义;2. 掌握栈和队列的应用,以及它们在解决实际问题中的作用;3. 提高算法设计能力和编程能力;4. 分析马踏棋盘问题的算法复杂度,并尝试优化算法。
三、实习内容1. 马踏棋盘问题介绍马踏棋盘问题是指在8x8的国际象棋棋盘上,将一匹马随机放在棋盘上的一个位置,然后按照国际象棋的走法,即“日”字形移动,使得马能够走遍棋盘上的所有方格。
要求使用非递归的方式实现。
2. 栈和队列的应用在解决马踏棋盘问题时,我们可以使用栈来存储马走过的路径,使用队列来实现广度优先搜索(BFS)策略,以寻找马的所有可能走法。
3. 算法实现(1)初始化棋盘和路径栈首先,我们需要初始化一个8x8的二维数组来表示棋盘,并将起始位置设置为(0,0)。
同时,创建一个栈来存储马走过的路径。
(2)定义马的移动规则根据国际象棋的规则,马可以走到以下八个位置之一:(-2,-1),(-2,1),(-1,-2),(-1,2),(1,-2),(1,2),(2,-1),(2,1)在实现时,我们需要判断这些位置是否在棋盘范围内,以及是否已经走过。
(3)广度优先搜索使用队列来实现广度优先搜索策略,从起始位置开始,按照BFS的顺序,依次尝试马的所有可能走法。
每走一步,就将新的位置压入栈中,并更新队列。
(4)输出结果当队列中所有位置都尝试过一遍后,栈中的路径即为马的行走路线。
按照路径输出棋盘上的数字,即可得到最终结果。
4. 算法优化为了提高算法的效率,我们可以考虑以下优化策略:(1)使用邻接矩阵来表示棋盘,减少重复计算;(2)在遍历队列时,优先考虑距离起始位置较近的位置;(3)在遍历过程中,避免重复访问已经访问过的位置。
图论探索之挑战奥数中的图论问题
图论探索之挑战奥数中的图论问题图论探索之挑战奥数中的图论问题图论是数学的一个重要分支,研究的是图的性质和图之间的关系。
在奥数竞赛中,图论问题常常被用来考察学生的逻辑推理和问题解决能力。
本文将介绍一些挑战奥数中常见的图论问题,并通过具体案例来解析。
1. 马踏棋盘问题马踏棋盘问题是一个经典的图论问题,要求马在棋盘上按照规定的移动方式遍历所有格子,且每个格子仅经过一次。
这个问题可以使用图的深度优先搜索来解决。
以8×8的棋盘为例,我们可以将每个格子看作图中的一个顶点,把马的移动看作图中的边。
通过搜索算法,可以找到一条路径,使得马可以遍历所有的格子。
2. 平面图的染色问题染色问题是图论中一个经典的问题,常被用来考察学生对图的颜色分配和连通性的理解。
平面图的染色问题要求给定的平面图在没有相邻顶点之间有相同颜色的情况下,尽可能使用最少的颜色进行染色。
通过贪心算法,可以解决平面图的染色问题。
贪心算法的基本思想是从一个初始解开始,每次选择可行的局部最优解,最终得到全局最优解。
对于平面图的染色问题,我们可以从一个顶点开始,按顺序给相邻的顶点染色,直到所有的顶点都被染色。
3. 电厂选址问题电厂选址问题是一个实际的应用问题,也可以用图论的方法来解决。
在电厂选址问题中,需要确定电厂的位置,使得电厂到各个需求点的距离和最短。
将电厂和需求点看作图中的顶点,电厂和需求点之间的距离看作边的权重。
通过最短路径算法,可以求解电厂选址问题。
常用的最短路径算法有Dijkstra算法和Floyd-Warshall算法,它们可以帮助我们找到电厂的最佳位置,以实现最优的供电方案。
4. 旅行商问题旅行商问题是图论中的一个经典问题,要求寻找一条路径,使得旅行商可以经过每个城市一次,并返回起点城市,且总路径长度最短。
旅行商问题是一个NP难问题,目前还没有高效的解法。
常用的解决方法是使用近似算法,例如最邻近算法和最小生成树算法。
这些算法可以找到一个接近最优解的解决方案。
马踏棋盘的实习报告
马踏棋盘实习报告题目:设计一个国际象棋的马踏遍棋盘的演示程序班级:姓名:学号:完成日期:一.需求分析将马随机放在m*n棋盘Board[m][n]的某个方格中,马按国际象棋行棋的规则进行移动。
要求每个方格只行走一次,走遍棋盘上全部m*n个方格。
编写非递归程序,求出马的行走路线,并按求出的行走路线,将数字1, 2, . m*n依次填入-一个m*n的方阵中。
程序要求:在国际象棋8×8棋盘上面,按照国际象棋规则中马的行进规则,实现从任意初始位置,每个方格只进入一次,走遍棋盘上全部64个方格。
编制程序,求出马的行走路线,并按求出的行走路线,将数字1,2,…,64依次填入一个8×8的方阵,并输出它的行走路线。
输入:任意一个起始位置;输出:无重复踏遍棋盘的结果,以数字1-64表示行走路线。
二.概要设计棋盘可用二维数组表示,马踏棋盘问题可采用回溯法解题。
当马位于棋盘某-位置时,它有唯一坐标,根据国际象棋的规则,它 6 7有8个方向可跳,对每一方向逐探测,从中选择可行方向继续行棋,每一行棋坐标借助栈记录。
若8个方向均不可行则借助栈回溯,在前一位置选择下一可行方向继续行棋,直至跳足m*n步,此时成功的走步记录在栈中。
或不断回湖直至栈空失败。
关于栈的抽象数据类型定义:否则返回ERRORPushStack( &s,SElemType e);操作结果:插入元素e为新的栈顶元素PopStack (&s,SElemType &e);操作结果:若栈不空,则删除s的栈顶元素,并用e返回其值,并返回OK;否则返回ERROR本程序包含以下模块:主程序模块:void main(){定义变量;接受命令;处理命令;退出;}起始坐标函数模块——马儿在棋盘上的起始位置;搜索路径函数模块——马儿每个方向进行尝试,直到试完整个棋盘;输出路径函数模块——输出马儿行走的路径模块调用关系:函数调用关系:三.详细设计#define OK 1#define TRUE 1#define ERROR 0#define FALSE 0#define M 8#define N 8int direction[2][9]={{0,-2,-1,1,2,2,1,-1,-2},{0,1,2,2,1,-1,-2,-2,-1}}; //增量数组int pow[M][N];int check[M][N],next[M][N]; //创建棋盘,初始为0struct Element //数据域{int x,y; //x行,y列int d; //下一步的方向};typedef struct LStack //链栈}*PLStack;typedef struct check //定义棋盘内点的坐标{int x;int y;}Check;/*************栈函数****************/ int InitStack(PLStack &S)//构造空栈{S=NULL;return OK;}int StackEmpty(PLStack S)//判断栈是否为空{if(S==NULL)return OK;elsereturn FALSE;}int Push(PLStack &S, Element e)//元素入栈PLStack p;p=(PLStack)malloc(sizeof(LStack));p->data=e;p->next=S;S=p;return OK;}int Pop(PLStack &S,Element &e) //元素出栈{PLStack p;if(!StackEmpty(S)){e=S->data;p=S;S=S->next;free(p);return OK;}/********贪心权值函数********/void Printf(int p[M][N]){ //打印权值数组for(int i=0;i<M;i++){for(int j=0;j<N;j++)printf(" %2d ",p[i][j]);printf("\n");}}void InitWeight(){ //创建权值数组并初始化每个位置的权值for(int i=0;i<M;i++)for(int j=0;j<N;j++)pow[i][j]=0;for(int i=0;i<M;i++){for(int j=0;j<N;j++){for(int dir=1;dir<=8;dir++){int x1=i+direction[0][dir];int y1=j+direction[1][dir];if(x1>=0&&x1<=7&&y1>=0&&y1<=7)pow[i][j]++;}}}}void SetWeight(int x,int y) { //位置(x,y)设置为被占用时,修改权值数组,被占用时为9pow[x][y]=9;for(int dir=1;dir<=8;dir++){int x1=x+direction[0][dir];int y1=y+direction[1][dir];if(x1>=0&&x1<=7&&y1>=0&&y1<=7&& pow[x1][y1]!=9)pow[x1][y1]--;}}void UnSetWeight(int x,int y){ //位置(x,y)设置为未占用时,修改权值数组for(int dir=1;dir<=8;dir++){ int x1=x+direction[0][dir];struct Element t,data;int pow_min=9;for(int dir=1;dir<=8;dir++){ //探测下一步可走的方向int x1=x+direction[0][dir];int y1=y+direction[1][dir];if(x1>=0&&x1<=7&&y1>=0&&y1<=7&& pow[x1][y1]!=9){if(pow_min>pow[x1][y1])//找出下一步位置中权值最小的{pow_min=pow[x1][y1];t.d=dir; //上一步的方向t.x=x1;t.y=y1;}}}data.x=x; //入栈data.y=y;data.d=t.d;Push(H,data);x=t.x; //坐标更新y=t.y;i++; //步数增加}PLStack H;InitStack(H);Check start;printf("请输入起始坐标x y:");scanf("%d%d",&start.x,&start.y);Step(start,H);Printf(check);return 0;}四.调试分析1.刚开始的时候并没有采用贪心算法,时间复杂度很大,探测量也很大。
棋盘算法实验报告(3篇)
个人自我介绍简单大方
很抱歉,但我无法为您提供____字的自我介绍。
以下是一个简洁而大方的自我介绍示例,供您参考:
大家好,我叫[姓名]。
很高兴有机会向大家介绍一下自己。
我出生并长大在[所在地],是一个勤奋、积极向上的人。
在学业方面,我于[毕业时间]从[学校名称]获得了[学位/专业]学位。
在大学期间,我通过自我努力和课外学习,取得了良好的学术成绩,并参与了一些学生组织和社团活动。
这些经历不仅培养了我的团队合作和领导能力,也加强了我的沟通和组织能力。
在工作方面,我有[工作年限]年的相关工作经验。
我曾在[公司/组织名称]担任[职位],负责[工作职责]。
在这期间,我不断努力提升自己的专业知识和技能,以适应快速发展的工作环境。
我善于分析问题并找出解决方案,能够有效地与团队合作并承担责任,这些都为我赢得了同事和上级的认可。
除了工作,我也积极参与志愿者活动,希望能为社区和弱势群体做一点贡献。
我相信,通过奉献和关心他人,我们可以建立一个更加和谐和温暖的社会。
在个人生活中,我喜欢阅读、旅行和运动。
阅读扩展了我的视野,旅行让我能够体验不同的文化和风景,而运动则让我保持健康和积极的精神状态。
此外,我也很喜欢与家人和朋友相处,分享彼此的喜怒哀乐。
总的来说,我是一个热情、乐观、有责任心的人。
我相信勤奋和坚持可以取得成功,而真诚和善良可以赢得他人的信任和支持。
我希望能够在您的团队中发挥我的才能,并与大家一同成长和进步。
这就是我简单的自我介绍,谢谢大家!。
马踏棋盘 数据结构实践报告
马踏棋盘问题摘要:马踏棋盘就是在国际象棋8X8棋盘上面,按照国际象棋规则中马的行进规则,实现从任意初始位置,每个方格只进入一次,走遍棋盘上全部64个方格。
理解栈的“后进先出”的特性以及学会使用回溯。
关键字:马踏棋盘、递归、栈、回溯1.引言马踏棋盘就是在国际象棋8X8棋盘上面,按照国际象棋规则中马的行进规则,实现从任意初始位置,每个方格只进入一次,走遍棋盘上全部64个方格。
编制程序,求出马的行走路线,并按求出的行走路线,将数字1,2….64依次填入一个8X8的方阵,并输出它的行走路线。
输入:任意一个起始位置;输出:无重复踏遍棋盘的结果,以数字1-64表示行走路线。
2.需求分析(1)需要输出一个8X8的棋盘,可以采用二维数组的方法实现。
(2)输入马的起始位置,必须保证输入的数字在规定范围内,即0<=X<=7,0<=Y<=7。
(3)保证马能走遍整个棋盘,并且不重复。
(4)在棋盘上输出马的行走路线,标记好数字1、2、3直到64。
3.数据结构设计采用栈数组为存储结构。
#define maxsize 100struct{int i;int j;int director;}stack[maxsize];4.算法设计4.1 马的起始坐标void location(int x,int y) //马的位置坐标的初始化{top++;stack[top].i=x; //起始位置的横坐标进栈stack[top].j=y; //起始位置的竖坐标进栈stack[top].director=-1;a[x][y]=top+1; //标记棋盘Try(x,y); //探寻的马的行走路线}4.2 路径探寻函数void Try(int i,int j){ int count,find,min,director;int i1,j1,h,k,s;intb[8]={-2,-2,-1,1,2,2,1,-1},c[8]={1,-1,-2,-2,-1,1,2,2};//存储马各个出口相对当前位置行、列坐标的增量数组int b2[8],b1[8];for(h=0;h<=7;h++)//用数组b1[8]记录当前位置的下一个位置的可行路径的条数{ count=0;i=stack[top].i+c[h];j=stack[top].j+b[h];if(i>=0&&i<=7&&j>=0&&j<=7&&a[i][j]==0)//如果找到下一个位置{for(k=0;k<=7;k++){i1=i+c[k];j1=j+b[k];if(i1>=0&&i1<=7&&j1>=0&&j1<=7&&a[i1][j1]==0) //如果找到下一个位置count++; //记录条数}b1[h]=count; //将条数存入b1[8]中}}for(h=0;h<=7;h++)//根据可行路径条数的大小,从小到大排序,并放入数组b2[8]中{min=9;for(k=0;k<=7;k++)if(min>b1[k]){min=b1[k];b2[h]=k;s=k;}b1[s]=9;}find=0;director=stack[top].director;for(h=director+1;h<=7;h++)//向8个方向进行寻找{i=stack[top].i+c[b2[h]];j=stack[top].j+b[b2[h]];if(i>=0&&i<=7&&j>=0&&j<=7&&a[i][j]==0){stack[top].director=h; //存储栈的寻找方向top++; //进栈stack[top].i=i;stack[top].j=j;stack[top].director=-1;//重新初始化下一栈的方向a[i][j]=top+1;find=1; //找到下一位置break;}}if(find!=1){a[stack[top].i][stack[top].j]=0; //清除棋盘的标记top--; //退栈}if(top<63)Try(i,j); //递归}4.3输出函数void display(){int i,j;for(i=0;i<=7;i++){ for(j=0;j<=7;j++)printf("\t%d ",a[i][j]); //输出马的行走路线printf("\n\n");}printf("\n");}5.程序实现5.1 主函数void main(){int i,j,x,y;for(i=0;i<=7;i++) //棋盘的初始化for(j=0;j<=7;j++)a[i][j]=0;printf("输入X Y (0=<X<=7,0=<Y<=7)\n");scanf("%d%d",&x,&y);if(x>=0&&x<=7&&y>=0&&y<=7)//判断输入的起始位子是否正确{location(x,y);display();}else printf("错误\n");}5.2运行结果(1)当输入不符合要求时(2)正确输入时5.3 算法分析(1)马的起始坐标一开始先建立一个栈数组,里面包括横坐标和竖坐标还有方向。
实验报告马踏棋盘
2.4题马踏棋盘题目:设计一个国际象棋的马踏棋盘的演示程序班级::学号:完成日期:一.需求分析(1)输入的形式和输入值的围:输入马的初始行坐标X和列坐标Y,X和Y的围都是[1,8]。
(2)输出形式:以数组下表的形式输入,i为行标,j为列标,用空格符号隔开。
以棋盘形式输出,每一格打印马走的步数,这种方式比较直观(3)程序所能达到的功能:让马从任意起点出发都能够遍历整个8*8的棋盘。
(4)测试数据,包括正确输入及输出结果和含有错误的输入及其输出结果。
数据可以任定,只要1<=x,y<=8就可以了。
正确的输出结果为一个二维数组,每个元素的值表示马行走的第几步,若输入有错,则程序会显示:“输入有误!请重新输入……”并且要求用户重新输入数据,直至输入正确为止。
二.概要设计(1)、位置的存储表示方式(2) typedef struct {int x;int y;int from;}Point;(2)、栈的存储方式#define STACKSIZE 70#define STACKINCREASE 10typedef struct Stack {Point *top;Point *base;int stacksize;};(1)、设定栈的抽象数据类型定义: ADT Stack {数据对象:D={ai | ai∈ElemSet,i=1,2,…,n,n≥0}数据关系:R1={<ai-1 , ai>|ai-1, ai∈D,i=2,…,n} 约定an端为栈顶,ai端为栈顶。
基本操作:InitStack(&s)操作结果:构造一个空栈s,DestroyStack(&s)初始条件:栈s已存在。
操作结果:栈s被销毁。
ClearStack(&s)初始条件:栈s已存在。
操作结果:栈s清为空栈。
StackEmpty(&s)初始条件:栈s已存在。
操作结果:若栈s为空栈,则返回TRUE,否则返回FALSE。
马踏棋盘算法
马踏棋盘算法介绍1.马踏棋盘算法,也称骑⼠周游问题2.规则:将马随机放在国际象棋的 8×8 棋盘[0~7][0~7]的某个⽅格中,马按⾛棋规则(马⾛⽇字)进⾏移动,要求每个⽅格只进⼊⼀次,⾛遍棋盘上全部 64 个⽅格3.基本思想:图的深度优先搜索 + 贪⼼算法(优化)步骤1.创建⼀个⼆维数组代表棋盘2.将当前位置设置为已经访问,把当前马在棋盘的位置标记为第⼏步(step),然后根据当前位置,计算马还能⾛哪些位置,并放⼊ArrayList,最多有8个位置3.获取到ArrayList后,⽤贪⼼算法优化4.遍历ArrayList中存放的所有位置,判断哪个位置可以⾛通,如果⾛通,就继续,⾛不通,就回溯5.判断是否⾛完整个棋盘,使⽤step和应该⾛的步数⽐较,如果没有达到数量,则表⽰没有完成任务,并将整个棋盘置0贪⼼算法优化ArrayList1.基本思想:根据当前这个⼀步的所有的下⼀步的选择位置,进⾏⾮递减(即不严格递增)排序,减少回溯的次数步骤(1)传⼊Comparotor,重写ArrayList的sort⽅法(2)获取ArrayList所有位置的通路个数,按⾮递减排序(3)即当前位置的下⼀步的下⼀步通路最少,就优先选择代码实现import java.awt.*;import java.util.ArrayList;import java.util.Arrays;import parator;public class KnightTravel {//骑⼠周游问题public int row;//棋盘的⾏数public int column;//棋盘的列数public int[][] chessboard;//棋盘public boolean[][] visited;//标记棋盘的各个位置是否被访问过,true:已访问public boolean finished;//标记是否棋盘的所有位置都被访问,若为true,表⽰算法计算成功public int step = 1;//初始为第⼀步public static void main(String[] args) {KnightTravel knight = new KnightTravel(8, 8);long start = System.currentTimeMillis();knight.travel(knight.chessboard, 0, 0, knight.step);long end = System.currentTimeMillis();System.out.println("共耗时: " + (end - start) + " 毫秒");knight.result();}public KnightTravel(int row, int column) {this.row = row;this.column = column;this.chessboard = new int[row][column];this.visited = new boolean[row][column];}public void result() {//打印算法结果for (int[] row : chessboard) {System.out.println(Arrays.toString(row));}}//马踏棋盘算法//chessboard:棋盘,row:马⼉当前的位置的⾏,从0开始,column:马⼉当前的位置的列,从0开始,step:第⼏步,初始位置是第1步 public void travel(int[][] chessboard, int row, int column, int step) {chessboard[row][column] = step;visited[row][column] = true; //标记该位置已经访问//获取当前位置可以⾛的下⼀个位置的集合ArrayList<Point> access = next(new Point(column, row));sort(access);//对access进⾏⾮递减排序while (!access.isEmpty()) {Point next = access.remove(0);//取出下⼀个可以⾛的位置if (!visited[next.y][next.x]) {//判断该点是否已经访问过travel(chessboard, next.y, next.x, step + 1);}}if (step < this.row * this.column && !finished) {//⽆路可⾛且未⾛完,就回溯到上⼀位置chessboard[row][column] = 0;visited[row][column] = false;} else {//成功⾛完时,finished是防⽌回溯时将最优解覆盖掉finished = true;}}//根据当前位置(curPoint),计算马还能⾛哪些位置(point),并放⼊⼀个集合中(ArrayList), 最多有8个位置public ArrayList<Point> next(Point curPoint) {//储存马在当前位置的通路ArrayList<Point> access = new ArrayList<>();//Point对象中,属性x代表列,属性y代表⾏Point point = new Point();//以下操作,判断马的8个⽅向是否可⾏,并记录通路位置,但不记录该位置是否已访问if ((point.x = curPoint.x - 2) >= 0 && (point.y = curPoint.y - 1) >= 0) {access.add(new Point(point));}if ((point.x = curPoint.x - 1) >= 0 && (point.y = curPoint.y - 2) >= 0) {access.add(new Point(point));}if ((point.x = curPoint.x + 1) < column && (point.y = curPoint.y - 2) >= 0) {access.add(new Point(point));}if ((point.x = curPoint.x + 2) < column && (point.y = curPoint.y - 1) >= 0) {access.add(new Point(point));}if ((point.x = curPoint.x + 2) < column && (point.y = curPoint.y + 1) < row) {access.add(new Point(point));}if ((point.x = curPoint.x + 1) < column && (point.y = curPoint.y + 2) < row) {access.add(new Point(point));}if ((point.x = curPoint.x - 1) >= 0 && (point.y = curPoint.y + 2) < row) {access.add(new Point(point));}if ((point.x = curPoint.x - 2) >= 0 && (point.y = curPoint.y + 1) < row) {access.add(new Point(point));}return access;}//根据当前这个⼀步的所有的下⼀步的选择位置,进⾏⾮递减(不严格递增)排序, 减少回溯的次数public void sort(ArrayList<Point> access) {access.sort(new Comparator<Point>() {@Overridepublic int compare(Point o1, Point o2) {int count1 = next(o1).size();int count2 = next(o2).size();if (count1 < count2) {return -1;} else if (count1 == count2) {return 0;} else {return 1;}}});}}。
棋盘上的不可能问题
49 6l 9
2 1 3 3
l 3 3 9
2 7
么 此 问 题有 解 么 ? 回答 是 否 定 的.
下面我们可以借助颜色来解 答. 国际 象棋 的棋盘是
2 9
7
5 9 4 7 3 5 4 5
l ☆
5 3 5组成 , 有八横行 和八竖 列. 马” “ 每跳一 次 , 总是 从一种颜 色的格子 , 跳到 另一种 颜 色的 格子. 例如“ ” 马 现在从 一黑 ( 白) 格跳 出, 直跳 一格 , 再
一
一
革
只“ 从左上 角的方格 ( 马” 图中标 5 0的方格 ) 出发 , 不
重 复 不 遗漏 地走 遍 整 张棋 盘 上 的每 一 个 格 子 , 后 到 达 最
格 出发 , 不重 复地 走遍整个 棋盘 上的每 一个格 子 , 最
右下角的那 个方格( 图中标为 1 8的方格 ) 呢? 大家可以动手 试一试 , 必须 注意 , 但 这个 问题 与 上
列里的和是常数 20 人们把这种数学方阵称作准勾方. 6,
首先按 照中国象棋 中马走 “ 字 的规 则 , 日” 竟然 可以 发现 中国马也可 以驰骋走天涯 , 即可 以从 任何 一点 出发
走遍 棋盘 上所有 的点. 于这 种现象 和结论 , 了用 常 对 除 规的试验证 实 , 为简洁方便 的方 法就是 转化 策略 : 最 把 马放 在棋盘 的任意一位置上 , 如果我们 能够证 明这个 马
1 9 4 3
5 5
斜跳一格或横一格 , 再斜跳一格 , 必跳 到 白( ) . 黑 格 跳三
次 时 , 是 从 黑 ( ) 跳 到 白 ( ) , 五 次 , 样 是 也 白 格 黑 格 跳 同
马踏棋盘——一个数据结构综合实验案例新解
总第 1 4卷 1 7期 5 21 0 2年 9月
大 众 科 技
P uar in e & Te h oo y op l e c Sc c n lg
Vo . 4 N0 9 L1 .
Se t pemb r 2 1 e 0 2
马踏 棋 盘
一 个 数 据 结构 综 合 实验 案 例 新解
知从 何 下 手 ,产 生 畏 难 心 理 ,会 打 击 学 生解 决 问题 的 自信 心 ;
而 案 例 过 于 简 单 , 则 达 不 到 综 合 实验 要 求 ,起 不 到锻 炼 学 生 的 目的 。一 个 合 适 的 综 合 实 验 案 例 ,应 该具 有 以 下几 个 特 点 :
课程打 下坚 实的基础 。然而 , 数据 结构也是一门理论性很强 的课程 ,理论 知识抽象 、概 念多 、算法 多而杂 ,学 生不好理 解 ,设 计程序无 从下手 。很 多学生反 映这 门课 “ 难懂 、不好 用 ”。学生不通 过实践很难对其 理论有深入 理解和应用 。因
Ab t a t I h sp p r t ep o lm f o s r v l g o h s b ad wa n r d c d i t a a s u t r x e me t e c i g a n s r c : n t i a e , h r b e o r eta ei n c e s o r si to u e n o d t t c u ee p r h n r i n a h n sa t
数学中的小马过河问题
数学中的小马过河问题
小马过河(马踏棋盘)问题是一个经典的搜索问题,它旨在寻找将一匹棋子从一个角落移动到另一个角落时所采取的最短路线。
问题是由英国数学家凯文·佩托于1800年代在《试论计算机算法理论》一书中首次提出。
解决小马过河问题的方法通常包括使用回溯法来搜索问题的状态空间,以寻找最佳解。
这种深度优先搜索算法确定每一步可行的可能性,并在发现这些可能性时尝试使用它们。
如果马在这个步骤之后无法达到目的地,将放弃该步骤,并回溯到上一个步骤。
回溯法应该是最终找到一条可以将马从开始位置抵达目的地的最短路径的算法。
另一个常用的解决此问题的方法是使用A*算法,它是一种搜索算法,用于从一个状态空间搜索到另一个状态空间的最优路径。
此算法综合考虑当前状态到目的状态的最短距离、路径节点可行性等标准来评估下一个可能的状态,从而最大限度地缩短搜索时间。
马踏棋盘的实习报告
马踏棋盘实习报告题目:设计一个国际象棋的马踏遍棋盘的演示程序班级:姓名:学号:完成日期:一.需求分析将马随机放在m*n棋盘Board[m][n]的某个方格中,马按国际象棋行棋的规则进行移动。
要求每个方格只行走一次,走遍棋盘上全部m*n个方格。
编写非递归程序,求出马的行走路线,并按求出的行走路线,将数字1, 2, . m*n依次填入-一个m*n的方阵中。
程序要求:在国际象棋8×8棋盘上面,按照国际象棋规则中马的行进规则,实现从任意初始位置,每个方格只进入一次,走遍棋盘上全部64个方格。
编制程序,求出马的行走路线,并按求出的行走路线,将数字1,2,…,64依次填入一个8×8的方阵,并输出它的行走路线。
输入:任意一个起始位置;输出:无重复踏遍棋盘的结果,以数字1-64表示行走路线。
二.概要设计棋盘可用二维数组表示,马踏棋盘问题可采用回溯法解题。
当马位于棋盘某-位置时,它有唯一坐标,根据国际象棋的规则,它 6 7有8个方向可跳,对每一方向逐探测,从中选择可行方向继续行棋,每一行棋坐标借助栈记录。
若8个方向均不可行则借助栈回溯,在前一位置选择下一可行方向继续行棋,直至跳足m*n步,此时成功的走步记录在栈中。
或不断回湖直至栈空失败。
关于栈的抽象数据类型定义:否则返回ERRORPushStack( &s,SElemType e);操作结果:插入元素e为新的栈顶元素PopStack (&s,SElemType &e);操作结果:若栈不空,则删除s的栈顶元素,并用e返回其值,并返回OK;否则返回ERROR本程序包含以下模块:主程序模块:void main(){定义变量;接受命令;处理命令;退出;}起始坐标函数模块——马儿在棋盘上的起始位置;搜索路径函数模块——马儿每个方向进行尝试,直到试完整个棋盘;输出路径函数模块——输出马儿行走的路径模块调用关系:函数调用关系:三.详细设计#define OK 1#define TRUE 1#define ERROR 0#define FALSE 0#define M 8#define N 8int direction[2][9]={{0,-2,-1,1,2,2,1,-1,-2},{0,1,2,2,1,-1,-2,-2,-1}}; //增量数组int pow[M][N];int check[M][N],next[M][N]; //创建棋盘,初始为0struct Element //数据域{int x,y; //x行,y列int d; //下一步的方向};typedef struct LStack //链栈}*PLStack;typedef struct check //定义棋盘内点的坐标{int x;int y;}Check;/*************栈函数****************/ int InitStack(PLStack &S)//构造空栈{S=NULL;return OK;}int StackEmpty(PLStack S)//判断栈是否为空{if(S==NULL)return OK;elsereturn FALSE;}int Push(PLStack &S, Element e)//元素入栈PLStack p;p=(PLStack)malloc(sizeof(LStack));p->data=e;p->next=S;S=p;return OK;}int Pop(PLStack &S,Element &e) //元素出栈{PLStack p;if(!StackEmpty(S)){e=S->data;p=S;S=S->next;free(p);return OK;}/********贪心权值函数********/void Printf(int p[M][N]){ //打印权值数组for(int i=0;i<M;i++){for(int j=0;j<N;j++)printf(" %2d ",p[i][j]);printf("\n");}}void InitWeight(){ //创建权值数组并初始化每个位置的权值for(int i=0;i<M;i++)for(int j=0;j<N;j++)pow[i][j]=0;for(int i=0;i<M;i++){for(int j=0;j<N;j++){for(int dir=1;dir<=8;dir++){int x1=i+direction[0][dir];int y1=j+direction[1][dir];if(x1>=0&&x1<=7&&y1>=0&&y1<=7)pow[i][j]++;}}}}void SetWeight(int x,int y) { //位置(x,y)设置为被占用时,修改权值数组,被占用时为9pow[x][y]=9;for(int dir=1;dir<=8;dir++){int x1=x+direction[0][dir];int y1=y+direction[1][dir];if(x1>=0&&x1<=7&&y1>=0&&y1<=7&& pow[x1][y1]!=9)pow[x1][y1]--;}}void UnSetWeight(int x,int y){ //位置(x,y)设置为未占用时,修改权值数组for(int dir=1;dir<=8;dir++){ int x1=x+direction[0][dir];struct Element t,data;int pow_min=9;for(int dir=1;dir<=8;dir++){ //探测下一步可走的方向int x1=x+direction[0][dir];int y1=y+direction[1][dir];if(x1>=0&&x1<=7&&y1>=0&&y1<=7&& pow[x1][y1]!=9){if(pow_min>pow[x1][y1])//找出下一步位置中权值最小的{pow_min=pow[x1][y1];t.d=dir; //上一步的方向t.x=x1;t.y=y1;}}}data.x=x; //入栈data.y=y;data.d=t.d;Push(H,data);x=t.x; //坐标更新y=t.y;i++; //步数增加}PLStack H;InitStack(H);Check start;printf("请输入起始坐标x y:");scanf("%d%d",&start.x,&start.y);Step(start,H);Printf(check);return 0;}四.调试分析1.刚开始的时候并没有采用贪心算法,时间复杂度很大,探测量也很大。
马踏棋盘非递归算法
马踏棋盘非递归算法1. 引言马踏棋盘问题是一个经典的数学问题,也是一个典型的回溯算法应用。
问题描述为:在一个空白的 n x n 棋盘上,放置一个马,马按照国际象棋中的规则移动,即每次可向前、向后、向左、向右移动两步,并且再往左或往右移动一步,或者再往前或往后移动一步。
目标是使得马在不重复访问任何一个格子的情况下,遍历整个棋盘。
本文将介绍一种非递归算法来解决马踏棋盘问题。
该算法使用了深度优先搜索和回溯的思想,通过栈来实现非递归遍历。
2. 算法思路2.1 数据结构为了实现非递归遍历,我们需要使用栈来保存当前已经访问过的格子。
我们还需要使用一个二维数组来表示棋盘,并记录每个格子被访问过的次数。
2.2 算法流程1.初始化棋盘和栈。
2.将起始位置压入栈中,并将起始位置标记为已访问。
3.进入循环,直到栈为空:–从栈顶取出当前位置。
–判断是否遍历完成,如果是,则输出遍历路径并结束算法。
–否则,获取当前位置的可行移动方向。
–对于每个可行方向,判断下一步是否越界且未访问过。
•如果满足条件,则将下一步位置压入栈中,并标记为已访问。
4.如果循环结束仍未找到解,则输出”无解”。
3. 算法实现3.1 初始化棋盘和栈def init_board(n):board = [[0] * n for _ in range(n)]return boarddef init_stack():stack = []return stack3.2 获取可行移动方向def get_directions(x, y, n):directions = []moves = [(-2, 1), (-1, 2), (1, 2), (2, 1),(2, -1), (1, -2), (-1, -2), (-2, -1)] for dx, dy in moves:nx = x + dxny = y + dyif nx >= 0 and nx < n and ny >= 0 and ny < n: directions.append((nx, ny))return directions3.3 马踏棋盘非递归算法def knight_tour(n, start_x, start_y):board = init_board(n)stack = init_stack()stack.append((start_x, start_y))board[start_x][start_y] = 1while stack:x, y = stack[-1]if board[x][y] == n * n:print_solution(board)returndirections = get_directions(x, y, n)next_directions = []for nx, ny in directions:if board[nx][ny] == 0:next_directions.append((nx, ny))if next_directions:nx, ny = next_directions.pop(0)stack.append((nx, ny))board[nx][ny] = board[x][y] + 1else:board[x][y] = 0stack.pop()print("无解")3.4 输出遍历路径def print_solution(board):n = len(board)for i in range(n):for j in range(n):print(board[i][j], end='\t')print()4. 示例与分析我们以一个 5 x 5 的棋盘为例,从起始位置 (0, 0) 开始进行遍历。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数学与计算科学学院综合性、设计性实验报告
实验室:06406实验日期:2015年05月29日
院(系)
信息与计算科学系
年级、专业、班
1300710226
姓名
庞文正
成绩
课程
名称
数据结构实验
实验项目
名 称
马踏棋盘问题
指导
教师
教师
评语
教师签名:
年 月 日
一 ,实验目的
加深对图的理解,培养解决实际问题的编程能力。根据数据对象的特性,学会数据组织的方
start.y--;
curstep=1; //第一步
Move(start); //求解
}
五,实验结果分析或总结
运行半天不出来,比如输入 2 2还以为算法有误,后来想通了,真开心!
{n");
scanf("%d%d",&start.x,&start.y);
}
else
{
break;
}
}
for(i=0;i<8;i++) //初始化棋盘个单元位置
{
for(j=0;j<8;j++)
{
chessboard[i][j]=0;
}
}
start.x--;
格子具有集合性,故考虑使用无向图来表示格子及其间关系;以邻接表作为该无向图中结点与相邻8个结点(4黑4白)的存储结构;以顶点表存储格子,每格为顶点表中一结点,其指针域指向该顶点所能到达的第一个结点。
表头结点:
Vex
x
y
link
Vex:头结点所在的序号
x:头结点所在的横坐标;
y:头结点所在的纵坐标;
link:指向Vex下一个能够到达的邻接结点
for(i=0;i<8;i++) //输出走法
{
for(j=0;j<8;j++)
{
printf("%5d",chessboard[i][j]);
}
printf("\n");
}
exit(0);
}
else //棋盘位置没走完
{
for(i=0;i<8;i++)
{
next.x=curpos.x+fangxiang[i].x;
{
{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2},{-2,-1}
};
void Move(Coordinate curpos) //马踏棋盘算法
{
Coordinate next;
int i,j;
if(curpos.x<0||curpos.x>7||curpos.y<0||curpos.y>7) //判断越界
curstep--; //减少步数
}
void main()
{
int i,j;
Coordinate start;
printf("马踏棋盘求解!\n");
printf("请输入马的一个起始位置(x,y):");
scanf("%d%d",&start.x,&start.y);
for(;;)
{
if(start.x<1||start.x>8||start.y<1||start.y>8) //判断输入值是否越界
链表中结点的结构同表头结点的结构同。在此不一一赘述了;
假定我们按照以下方式对棋盘上的格子进行编号(如红色标注),那么编号与格子所在的坐标(如蓝色标注)位置必然存在一定关系。(留给大家思考)
21(1,5)
22(2,5)
23(3,5)
24(4,5)
25(5,5)
16(1,4)
17(2,4)
18(3,4)
19(4,4)
20(5,4)
11(1,3)
12(2,3)
13(3,3)
14(4,3)
15(5,3)
6(1,2)
7(2,2)
8(3,2)
9(4,2)
10(5,2)
1(1,1)
2(2,1)
3(3,1)
4(4,1)
5(5,1)
综合起来,马踏棋盘问题就可以转化为图的遍历问题。
三,使用仪器,材料
XP系统电脑一台,vc++软件!
四,实验内容与步骤
#include<stdio.h>
#include<stdlib.h>
typedef struct
{
int x;
int y; //棋盘上的坐标
}Coordinate;
int chessboard[8][8];; //棋盘
int curstep; //马跳的步骤序号
Coordinate fangxiang[8]= //马可走的方向
法,把现实世界中的实际问题在计算机内部表示出来,培养基本的、良好的程序设计技能。
二,实验原理
整个棋盘可表示为一个M×N的二维数组。假若马目前在位置(i,j)则马下一步可移动的位置0、1、……、7可分别表示为(i-2,j+1),(i-1,j+2),(i+1,j+2),(i+2,j+1),(i+2,j-1),(i+1,j-2), (i-1,j-2), (i-2,j-1)。当然,这些位置一定在棋盘边界以内(保证下一步移动位置坐标(i,j),有0<i<M+1,0<j<N+1)。
next.y=curpos.y+fangxiang[i].y;
if(curpos.x<0||curpos.x>7||curpos.y<0||curpos.y>7) //如果越界,不做任何处理
{
}
else //否则进行移动
{
Move(next);
}
}
}
chessboard[curpos.x][curpos.y]=0; //清除步数序号
{
return ;
}
if(chessboard[curpos.x][curpos.y]) //如果已走过,直接返回
{
return ;
}
chessboard[curpos.x][curpos.y]=curstep; //保存步骤数
curstep++;
if(curstep>64) //棋盘位置都走完了
{