跳马问题、骑士遍历问题
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
跳马问题
跳马问题也称骑士遍历问题:在n*n 方格的棋盘上,从任意指定的方格出发, 为象棋中的马寻找一条走遍棋盘每一格并 且只经过一次的一条路径。
Байду номын сангаас
问题分析
如下图所示,一只马在棋盘的某一点,它可以朝8 个方向前进,方向向量分别是: (-2,1)、 (-1,2) (1,2)、 (2,1)、(2,-1) 、(1,-2)、 (-1,-2)、(-2,-1)。
代码
#include<iostream.h> #include <time.h> #include <stdlib.h> const int n=6; // 表示棋盘的长和高n int qipan[n+1][n+1]; // 记录棋盘是否被跳过 static int cmq; // 步数 int OK=0; // 没有被使用 int xLabel,yLabel; void shuchu() { cout<<'\t'; for(int i1=1;i1<=n;i1++) cout<<i1<<"列"<<'\t'; for(int i=1;i<=n;i++) { cout<<endl; cout<<i<<"行"<<'\t'; for(int j=1;j<=n;j++) { cout<<qipan[i][j]<<'\t'; } cout<<endl; } }
// 回朔
int main() { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) qipan[i][j]=0; for(i=1;i<=n;i++) //该处分别计算从点(1,1)到点(n,n)作为起始点,可以找到哪些回路 for(int j=1;j<=n;j++) { xLabel= i; yLabel = j; cmq = 1; for(int k1=1;k1<=n;k1++) for(int k2=1;k2<=n;k2++) qipan[k1][k2]=0; qipan[i][j] = 1; tiaoma(i,j); } if(OK!=1) { cout<<endl<<"当n="<<n<<"时无回路"<<endl; } return 0; }
int tiaoma(int x,int y) { if(cmq ==n*n && ((x-2==xLabel && y+1 == yLabel) ||(x-1==xLabel && y+2 == yLabel) ||(x+1==xLabel && y+2== yLabel) || (x+2 == xLabel && y+1 == yLabel) ||(x+2 == xLabel && y-1 == yLabel) ||(x+1== xLabel && y-2==yLabel) ||(x-2==xLabel && y-1==yLabel) ||(x-1==xLabel && y-2==yLabel))) { shuchu(); OK=1; return 0; } if(1 <= x-2 && y+1 <= n && qipan[x-2][y+1] == 0) { qipan[x-2][y+1]=++cmq; // 1 tiaoma(x-2,y+1); } if(1<=x-1&&y+2<=n&&qipan[x-1][y+2]==0) { qipan[x-1][y+2]=++cmq; // 2 tiaoma(x-1,y+2); } if(x+1<=n&&y+2<=n&&qipan[x+1][y+2]==0) { qipan[x+1][y+2]=++cmq; // 3 tiaoma(x+1,y+2); } if(x+2<=n&&y+1<=n&&qipan[x+2][y+1]==0) { qipan[x+2][y+1]=++cmq; // 4 tiaoma(x+2,y+1); }
从中任选择一个方向前进,到达新的位置。 在从新的位置选择一个方向前进,继续,直 到无法前进为止。无法前进可能有如下原因: 下一位置超出边界、下一位置已经被访问过。 当马已经无法前进时,就回退到上一位置, 从新选择一个新的方向前进;如果还是无法 前进,就再回退到上一位置,以此类推。
经分析,本问题可以运用回溯法的思想求解: 1.该问题的解空间的组织形式是一颗八叉树, 一个可行的解就是从根节点到叶子节点的一 条路径。 2.控制策略则是马必须在棋盘内。
if(x+2<=n&&1<=y-1&&qipan[x+2][y-1]==0) { qipan[x+2][y-1]=++cmq; // 5 tiaoma(x+2,y-1); } if(x+1<=n&&1<=y-2&&qipan[x+1][y-2]==0) { qipan[x+1][y-2]=++cmq; // 6 tiaoma(x+1,y-2); } if(1<=x-1&&1<=y-2&&qipan[x-1][y-2]==0) { qipan[x-1][y-2]=++cmq; // 7 tiaoma(x-1,y-2); } if(1<=x-2&&1<=y-1&&qipan[x-2][y-1]==0) { qipan[x-2][y-1]=++cmq; // 8 tiaoma(x-2,y-1); } cmq --; qipan[x][y] = 0; return 0; }
跳马问题也称骑士遍历问题:在n*n 方格的棋盘上,从任意指定的方格出发, 为象棋中的马寻找一条走遍棋盘每一格并 且只经过一次的一条路径。
Байду номын сангаас
问题分析
如下图所示,一只马在棋盘的某一点,它可以朝8 个方向前进,方向向量分别是: (-2,1)、 (-1,2) (1,2)、 (2,1)、(2,-1) 、(1,-2)、 (-1,-2)、(-2,-1)。
代码
#include<iostream.h> #include <time.h> #include <stdlib.h> const int n=6; // 表示棋盘的长和高n int qipan[n+1][n+1]; // 记录棋盘是否被跳过 static int cmq; // 步数 int OK=0; // 没有被使用 int xLabel,yLabel; void shuchu() { cout<<'\t'; for(int i1=1;i1<=n;i1++) cout<<i1<<"列"<<'\t'; for(int i=1;i<=n;i++) { cout<<endl; cout<<i<<"行"<<'\t'; for(int j=1;j<=n;j++) { cout<<qipan[i][j]<<'\t'; } cout<<endl; } }
// 回朔
int main() { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) qipan[i][j]=0; for(i=1;i<=n;i++) //该处分别计算从点(1,1)到点(n,n)作为起始点,可以找到哪些回路 for(int j=1;j<=n;j++) { xLabel= i; yLabel = j; cmq = 1; for(int k1=1;k1<=n;k1++) for(int k2=1;k2<=n;k2++) qipan[k1][k2]=0; qipan[i][j] = 1; tiaoma(i,j); } if(OK!=1) { cout<<endl<<"当n="<<n<<"时无回路"<<endl; } return 0; }
int tiaoma(int x,int y) { if(cmq ==n*n && ((x-2==xLabel && y+1 == yLabel) ||(x-1==xLabel && y+2 == yLabel) ||(x+1==xLabel && y+2== yLabel) || (x+2 == xLabel && y+1 == yLabel) ||(x+2 == xLabel && y-1 == yLabel) ||(x+1== xLabel && y-2==yLabel) ||(x-2==xLabel && y-1==yLabel) ||(x-1==xLabel && y-2==yLabel))) { shuchu(); OK=1; return 0; } if(1 <= x-2 && y+1 <= n && qipan[x-2][y+1] == 0) { qipan[x-2][y+1]=++cmq; // 1 tiaoma(x-2,y+1); } if(1<=x-1&&y+2<=n&&qipan[x-1][y+2]==0) { qipan[x-1][y+2]=++cmq; // 2 tiaoma(x-1,y+2); } if(x+1<=n&&y+2<=n&&qipan[x+1][y+2]==0) { qipan[x+1][y+2]=++cmq; // 3 tiaoma(x+1,y+2); } if(x+2<=n&&y+1<=n&&qipan[x+2][y+1]==0) { qipan[x+2][y+1]=++cmq; // 4 tiaoma(x+2,y+1); }
从中任选择一个方向前进,到达新的位置。 在从新的位置选择一个方向前进,继续,直 到无法前进为止。无法前进可能有如下原因: 下一位置超出边界、下一位置已经被访问过。 当马已经无法前进时,就回退到上一位置, 从新选择一个新的方向前进;如果还是无法 前进,就再回退到上一位置,以此类推。
经分析,本问题可以运用回溯法的思想求解: 1.该问题的解空间的组织形式是一颗八叉树, 一个可行的解就是从根节点到叶子节点的一 条路径。 2.控制策略则是马必须在棋盘内。
if(x+2<=n&&1<=y-1&&qipan[x+2][y-1]==0) { qipan[x+2][y-1]=++cmq; // 5 tiaoma(x+2,y-1); } if(x+1<=n&&1<=y-2&&qipan[x+1][y-2]==0) { qipan[x+1][y-2]=++cmq; // 6 tiaoma(x+1,y-2); } if(1<=x-1&&1<=y-2&&qipan[x-1][y-2]==0) { qipan[x-1][y-2]=++cmq; // 7 tiaoma(x-1,y-2); } if(1<=x-2&&1<=y-1&&qipan[x-2][y-1]==0) { qipan[x-2][y-1]=++cmq; // 8 tiaoma(x-2,y-1); } cmq --; qipan[x][y] = 0; return 0; }