马踏棋盘(骑士周游问题)

  • 一、马踏棋盘概述
  • 二、马踏棋盘思路
  • 三、马踏棋盘代码实现(java)
  • 四、马踏棋盘代码实现(C)

一、马踏棋盘概述

(1)马踏棋盘算法也被称为骑士周游问题
(2)玩法:将马随机放在国际象棋的8×8棋盘Board[0~7]的某个方格中,马按走棋规则(马走日字)进行移动。要求每个方格只进入一次,走遍棋盘上全部64个方格

关于马的走法:

二、马踏棋盘思路

1、马踏棋盘问题(骑士周游问题)实际上是图的深度优先搜索(DFS)的应用。
2、解决步骤与思路:
(1)创建棋盘(chessBoard),是一个二维数组;
(2)将当前位置设置为已经访问,然后根据当前位置,计算马能走哪些位置,并放入到一个集合中(ArrayList),最多有8个位置,每走一步,就使用step+1;
(3)通过贪心算法进行优化:根据当前这一步的所有的下一步的选择位置,进行非递减排序(例如:1,2,2,2,3,3,4就属于非递减排序);
(4)遍历ArrayList中存放的所有位置,看看哪个可以走通,如果走通,就继续,走不通,就回溯;
(5)判断马是否完成了任务,使用step和应该走的步数比较,如果没有达到数量,则表示没有完成任务,将整个棋盘置为0。

注意:马的不同走法,会得到不同的结果,效率也会有影响。这个在用贪心算法进行优化时,效率也会受到影响。

三、马踏棋盘代码实现(java)

import java.awt.Point;
import java.util.ArrayList;
import java.util.Comparator;public class test {private static int X; // 棋盘的列数private static int Y; // 棋盘的行数//创建一个数组,标记棋盘的各个位置是否被访问过private static boolean visited[];//使用一个属性,标记是否棋盘的所有位置都被访问private static boolean finished; // 如果为true,表示成功public static void main(String[] args) {//测试骑士周游算法是否正确X = 8;Y = 8;int row = 1; //马儿初始位置的行,从1开始编号int column = 1; //马儿初始位置的列,从1开始编号//创建棋盘int[][] chessboard = new int[X][Y];visited = new boolean[X * Y];//初始值都是falsetraversalChessboard(chessboard, row - 1, column - 1, 1);//输出棋盘的最后情况for(int[] rows : chessboard) {for(int step: rows) {System.out.print(step + "\t");}System.out.println();}}/*** 完成骑士周游问题的算法* @param chessboard 棋盘* @param row 马儿当前的位置的行 从0开始* @param column 马儿当前的位置的列  从0开始* @param step 是第几步 ,初始位置就是第1步*/public static void traversalChessboard(int[][] chessboard, int row, int column, int step) {chessboard[row][column] = step;//row = 4 X = 8 column = 4 = 4 * 8 + 4 = 36visited[row * X + column] = true; //标记该位置已经访问//获取当前位置可以走的下一个位置的集合ArrayList<Point> ps = next(new Point(column, row));//对ps进行排序,排序的规则就是对ps的所有的Point对象的下一步的位置的数目,进行非递减排序sort(ps);//遍历 pswhile(!ps.isEmpty()) {Point p = ps.remove(0);//取出下一个可以走的位置//判断该点是否已经访问过if(!visited[p.y * X + p.x]) {//说明还没有访问过traversalChessboard(chessboard, p.y, p.x, step + 1);}}//判断马是否完成了任务,使用 step 和应该走的步数比较 ,//如果没有达到数量,则表示没有完成任务,将整个棋盘置0//说明: step < X * Y  成立的情况有两种//1. 棋盘到目前位置,仍然没有走完//2. 棋盘处于一个回溯过程if(step < X * Y && !finished ) {chessboard[row][column] = 0;visited[row * X + column] = false;} else {finished = true;}}/*** 根据当前位置(Point对象),计算马还能走哪些位置(Point),并放入到一个集合中(ArrayList), 最多有8个位置* @param curPoint* @return*/public static ArrayList<Point> next(Point curPoint) {//创建一个ArrayListArrayList<Point> ps = new ArrayList<Point>();//创建一个PointPoint p1 = new Point();//表示马儿可以走5这个位置if((p1.x = curPoint.x - 2) >= 0 && (p1.y = curPoint.y -1) >= 0) {ps.add(new Point(p1));}//判断马儿可以走6这个位置if((p1.x = curPoint.x - 1) >=0 && (p1.y=curPoint.y-2)>=0) {ps.add(new Point(p1));}//判断马儿可以走7这个位置if ((p1.x = curPoint.x + 1) < X && (p1.y = curPoint.y - 2) >= 0) {ps.add(new Point(p1));}//判断马儿可以走0这个位置if ((p1.x = curPoint.x + 2) < X && (p1.y = curPoint.y - 1) >= 0) {ps.add(new Point(p1));}//判断马儿可以走1这个位置if ((p1.x = curPoint.x + 2) < X && (p1.y = curPoint.y + 1) < Y) {ps.add(new Point(p1));}//判断马儿可以走2这个位置if ((p1.x = curPoint.x + 1) < X && (p1.y = curPoint.y + 2) < Y) {ps.add(new Point(p1));}//判断马儿可以走3这个位置if ((p1.x = curPoint.x - 1) >= 0 && (p1.y = curPoint.y + 2) < Y) {ps.add(new Point(p1));}//判断马儿可以走4这个位置if ((p1.x = curPoint.x - 2) >= 0 && (p1.y = curPoint.y + 1) < Y) {ps.add(new Point(p1));}return ps;}//根据当前这一步的所有的下一步的选择位置,进行非递减排序, 减少回溯的次数public static void sort(ArrayList<Point> ps) {ps.sort(new Comparator<Point>() {@Overridepublic int compare(Point o1, Point o2) {// TODO Auto-generated method stub//获取到o1的下一步的所有位置个数int count1 = next(o1).size();//获取到o2的下一步的所有位置个数int count2 = next(o2).size();if(count1 < count2) {return -1;} else if (count1 == count2) {return 0;} else {return 1;}}});}
}

结果如下

四、马踏棋盘代码实现(C)

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define Row 8
#define Col 8
#define maxStep 64typedef struct {int abscissa;  //横坐标int ordinate;  //纵坐标int direction;  //方向
}SqStack;int ChessBoard[Row+1][Col+1]={}; //储存路径的棋盘//分别有(1 ~ 8)个方向
int HTry1[8]={1, -1, -2, 2, 2, 1, -1, -2};
int HTry2[8]={2, -2, 1, 1, -1, -2, 2, -1};SqStack PointStack[maxStep];
int top = -1; //栈顶int flagOperate = 1; //操作标记
int num = 0;  //记录结果数void printChessBoard() {printf("棋盘路径是:\n");for(int i = 1;i <= Row;i++) {for(int j = 1;j <= Col;j++) {printf("%5d ", ChessBoard[i][j]);}printf("\n");}printf("\n\n");
}//入栈
void push(int abscissa, int ordinate) {++top;PointStack[top].abscissa = abscissa;PointStack[top].ordinate = ordinate;PointStack[top].direction = -1; //初始化方向
}//出栈
void pop() {PointStack[top].abscissa = 0;PointStack[top].ordinate = 0;PointStack[top].direction = -1; //初始化方向--top;
}//打印栈
void printStack() {printf("目前栈的情况:\n");for(int i = 0;i < maxStep;i++) {printf("x:%d , y:%d, d:%d\n", PointStack[i].abscissa, PointStack[i].ordinate, PointStack[i].direction);}printf("\n\n");
}//标记棋盘
void markChessBoard(int abscissa, int ordinate) {ChessBoard[ordinate][abscissa] = top+1;
}void runChessBoard() {int xNow, yNow; //当前马所在的坐标while(1) {if(flagOperate == 1) {if(top == maxStep - 1) {printChessBoard();break;}}xNow = PointStack[top].abscissa;yNow = PointStack[top].ordinate;//对下面八个方向重新排序,出口最少的优先int count[8]={};for(int i = 0;i < 8;i++) {int xNext = xNow, yNext = yNow;xNext += HTry1[i];yNext += HTry2[i];if(xNext > 0 && xNext <= Col && yNext > 0 && yNext <= Row && ChessBoard[yNext][xNext] == 0) {for(int j = 0;j < 8;j++) {int xNextNext = xNext, yNextNext = yNext;xNextNext += HTry1[j];yNextNext += HTry2[j];if(xNextNext > 0 && xNextNext <= Col  && yNextNext > 0 && yNextNext <= Row && ChessBoard[yNextNext][xNextNext] == 0) {count[i]++;}}}}//对方向进行排序,实际要走的方向记录在directionNext中int directionNext[8] = {};int temp = 9;int  k = 0;for(int i = 0;i < 8;i++) {temp = 9;for(int j = 0;j < 8;j++) {if(count[j]<temp){directionNext[i] = j;temp = count[j];k = j;}}count[k] = 9;}//走下一步int direnow = 0;for(direnow = PointStack[top].direction + 1 ; direnow < 8 ; direnow++) {int xRealNext = xNow, yRealNext = yNow;xRealNext += HTry1[directionNext[direnow]];yRealNext += HTry2[directionNext[direnow]];PointStack[top].direction += 1;if(xRealNext <= Col && xRealNext > 0 && yRealNext <= Row && yRealNext > 0 &&ChessBoard[yRealNext][xRealNext] == 0) {push(xRealNext, yRealNext);markChessBoard(xRealNext, yRealNext);break;}}//判断无路可走出栈if(PointStack[top].direction >= 7) {int x, y;x = PointStack[top].abscissa;y = PointStack[top].ordinate;ChessBoard[y][x] = 0; //棋盘标记取消pop();}}
}void InitStartPoint() {int x, y;//输入起始坐标点printf("请输入起始点(x,y):");scanf("%d,%d", &x, &y);while(((x > Col||x <= 0)||(y > Row||y <= 0))) {if((x > Col||x <= 0)||(y > Row||y <= 0)) {printf("输入的坐标超出范围,请重新输入(0~8):");scanf("%d,%d", &x, &y);}}//入首栈push(x, y);markChessBoard(x, y);
}int main() {InitStartPoint();clock_t start,finish; //开始结束时间double duration;  //运行用时start = clock();runChessBoard();finish = clock();duration = (double) (finish - start) / CLOCKS_PER_SEC;printf("运行用时: %f second\n", duration);
}

结果如下


楠哥-------一心想为IT行业添砖加瓦,却总是面向cv编程的程序员。
  谢谢阅读,无误点赞,有误还望评论区指正。


马踏棋盘(骑士周游问题)相关推荐

  1. 【数据结构与算法】马踏棋盘(骑士周游世界)算法

    一,基本介绍 1)马踏棋盘算法也称为骑士周游问题 2)将马随机放在国际象棋的8 × 8棋盘Board[0~7] [0~7]的某个方格中,马按走棋规则(马走日字)进行移动.要求每个方格只进入一次,走遍棋 ...

  2. 【算法】马踏棋盘算法 骑士走周游算法

    文章目录 1.概述 2.贪心优化 1.概述 马踏棋盘算法和八皇后问题很相似:[算法]八皇后问题 骑士周游问题的解决步骤和思路 创建棋盘chessBoard,是一个二维数组 将当前位置设置为已经访问,然 ...

  3. 骑士周游(马踏棋盘)问题

    1,马踏棋盘算法介绍 马踏棋盘问题也被称为骑士周游问题 将马随机放在国际象棋的8*8的棋盘中的某个格子里,马按照走棋规则(日子)进行移动.要求每个方格只进入一次,走遍64个方格 2,马踏棋盘算法思路分 ...

  4. Java对马踏棋盘问题(骑士周游问题)的实现

    14.10.2 马踏棋盘游戏代码实现 马踏棋盘问题(骑士周游问题)实际上是图的深度优先搜索(DFS)的应用. 如果使用回溯(就是深度优先搜索)来解决,假如马儿踏了 53 个点,如图:走到了第 53 个 ...

  5. 马踏棋盘算法(骑士周游问题)

    要求: 国家棋盘为8*8的方格棋盘,将"马"放在任意指定方格中.最终让马走遍64个方格. 关于象棋中马的走法 如下图所示: 下面是代码: #include <stdio.h& ...

  6. 残缺棋盘问题算法分析_javascript使用递归回溯算法和贪心算法解决马踏棋盘问题...

    马踏棋盘算法介绍和游戏演示 1.马踏棋盘算法也被称为骑士周游问题 2.将马随机放在国际象棋的8×8棋盘Board[0-7][0-7]的某个方格中,马按走棋规则(马走日字)进行移动.要求每个方格只进入一 ...

  7. java 马踏棋盘优化_我所知道的十大常用算法之马踏棋盘算法(深度搜索、贪心思想优化 )...

    前言需求 今天我们学习的是马踏棋盘算法,我们还是从一个场景里引入看看 马踏棋盘算法也被称为骑士周游问题 将马随机放在国际象棋的6×6棋盘Board0-5的某个方格中 提示:马按走棋规则(马走日字)进行 ...

  8. 数据结构与算法|马踏棋盘算法(小甲鱼)C语言代码的算法分析

    马踏棋盘算法(骑士周游问题)的算法分析 C语言代码部分来自小甲鱼的<数据结构与算法> 文章目录 马踏棋盘算法(骑士周游问题)的算法分析 一.C语言代码实现 二.代码分析与算法思路 题目要求 ...

  9. Day600601.马踏棋盘算法 -数据结构和算法Java

    马踏棋盘算法 图的深度优先DFS 回溯 八皇后问题.小老鼠找迷宫问题 一.介绍 二.思路分析 三.代码实现 package com.achang.algorithm;import java.awt.* ...

  10. 数据结构(七)——Dijkasta 、Flyod、马踏棋盘算法

    Dijkstra 算法 应用场景-最短路径问题 有 7 个村庄(A, B, C, D, E, F, G) ,现在有六个邮差,从 G 点出发,需要分别把邮件分别送到A, B, C , D, E, F 六 ...

最新文章

  1. Python3 高级特性
  2. python安装绘图库matplotlib_Python基础教程:Python 2D绘图库 Matplotlib 简介和安装
  3. pythonddos防御_浅谈拒绝服务攻击的原理与防御(7):用Python和C实现syn flood攻击...
  4. 第四章:Django 模型 —— 设计系统表
  5. Android之多线程----异步消息处理机制之Handler详解
  6. 前端学习(3026):vue+element今日头条管理-调整外观
  7. mips指令分类和寻址大全
  8. Spring Boot 项目中Java对象的字符串类型属性值转换为JSON对象的布尔类型键值的解决方法及过程
  9. 【体系结构】一条SQL语句经历了什么
  10. 张莉python 玩转数据答案_中国大学MOOC(慕课)用Python玩转数据答案大全
  11. 服务器操作记录21/11/19
  12. 阿尔派X09电脑调音软件 DSP调音软件下载
  13. 简单的TCP客户端发包工具
  14. nexus3作为docker私服的使用
  15. Aliplayer的各种坑
  16. html更改提示框内容,JS修改内容提示框字体样式
  17. 第39级台阶(递归+dp)
  18. docker打包镜像--go语言编写的http项目
  19. pacs系统服务器配置需求,pacs系统服务器配置
  20. Dell笔记本 BIOS改硬盘模式Raid改为ahci,开机蓝屏0xc0000001

热门文章

  1. java 基于jave2实现视频处理 截屏,加水印,压缩,获取时长
  2. 在win2012上安装OfficeScan12控制台显示IIS服务未启动的解决办法
  3. 区块链社会:解码区块链全球应用与投资案例
  4. 移动硬盘插电脑上驱动感叹号_如何通过移动驱动器向手机或平板电脑添加额外的存储空间...
  5. phpddos***器1.0-6.0
  6. SnakeMaker:模仿实现 即刻APP 头像拖动的残影效果
  7. vscode解决方案 关闭源代码管理
  8. HTML5移动应用开发为什么需要引入前端工程化
  9. QT自定义QmessageBox对话框
  10. 2013年最具有技术影响力原创图书评选