马踏棋盘(从低效到高效)

2023-11-09 05:10
文章标签 高效 棋盘 低效 马踏

本文主要是介绍马踏棋盘(从低效到高效),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目描述

将棋子“马”随机的放在国际象棋棋盘Board[8][8]的某个方格中,“马”按走棋规则进行移动,要求每个方格只进入一次,走遍棋盘上所有的64个方格。

题目要求

编写非递归程序,求出“马”的行走路线,并按求出的行走路线将数字1-64依次填入一个8x8的方阵并输出。

分析 x 1

一看题目说是8x8棋盘,要求走遍棋盘,首先想到的便是直接深搜即可,但是后面说到要求非递归程序,这也简单,自己把递归的那一部分
改为用栈来实现即可(马走棋盘肯定会遇到走不下去的情况,所以需要储存之前已经走过的点,而“悔棋”肯定是从当前这一步往之前返
回,所以是一个后进先出的结构——栈)。
定义
typedef struct _horse
{int x;  //横坐标int y;  //纵坐标int s;  //下一步的方向
}HORSE;
int chessboard[8][8];   //棋盘
int Next[8][2] = {{2,1}, {1,2}, {-1,2}, {-2,1}, {-2,-1}, {-1,-2}, {1,-2}, {2,-1}};  //方向
int cnt = 1;            //计数器
stack<HORSE> horse;
执行函数
bool judge(int a, int b)
{if(a < 0 || a > 7 || b < 0 || b > 7)    //边界return false;return true;
}void Horse(int x, int y)
{HORSE temp;int a,b;	//记录当前马位置附近的坐标int i = 0;chessboard[x][y] = cnt;	//标记当前起始位置已被访问 temp.x = x;	//记录当前马的位置temp.y = y;while(cnt < 64){for(; i < 8; i++){a = temp.x + Next[i][0];b = temp.y + Next[i][1];if(judge(a,b) && chessboard[a][b] == 0)     //判断{break;}}if(i < 8)	//能够访问当前马位置附近的日点{chessboard[a][b] = ++cnt;temp.s = i;horse.push(temp);memset(&temp, 0, sizeof(HORSE));temp.x = a;temp.y = b;i = 0;}else	//回溯{--cnt;chessboard[temp.x][temp.y] = 0;HORSE tt = horse.top();horse.pop();temp.x = tt.x;temp.y = tt.y;i = tt.s;++i;	//继续搜索从当前马位置访问的点的下一个点继续访问}}
}

完成后测试了一下,只有(0,0)可以跑出来,可见这种暴力的方式效率实在是太低…

分析 x 2

上面的暴力试探方式效率实在太低了,所以我们要优化一下代码。
把书继续往后翻,有提到将马的初始步入栈,计算其8个方向的权值,将其按升序排列,马从最小权值的点开始走,
无路可走时回溯(权值就是一个点下一步能走的点的总数)。
这是一种贪心的思想,那么既然是贪心,我们可不可以再贪心一些,每一步直接走权值最小的点,不再回溯,看能不能走完。
执行函数
void Horse(int x, int y)
{HORSE temp;int a,b;    //记录当前马位置附近的坐标chessboard[x][y] = cnt; //标记当前起始位置已被访问 temp.x = x; //记录当前马的位置temp.y = y;while(cnt < 64){int h_min = 8;      //权值最小的点int tx,ty,ti;       //记录权值最小的点的信息for(int i = 0; i < 8; i++){a = temp.x + Next[i][0];b = temp.y + Next[i][1];if(judge(a,b) && chessboard[a][b] == 0)     //判断{int step = steps(a,b);   //计算权值if(step < h_min)         //更新权值最小的点{h_min = step;    tx = a;ty = b;ti = i;}            }}//直接走权值最小的点chessboard[tx][ty] = ++cnt;temp.s = ti;//temp.step = h_min;horse.push(temp);memset(&temp, 0, sizeof(HORSE));temp.x = tx;temp.y = ty;}
}

这次测试了一下,效率大大的提高了,但是我们是“最”贪心的方法,所以我们要测试一下,看能不能从任意点出发都能走完棋盘。
经过测试有一个点不能走完棋盘,就是(2,4),也就是三行五列的点。

分析 x 3

好吧,既然只有一个点不能按照我们最贪心的方式走完,那么我们就只对这一个点特殊处理一下。
处理方式即就是分析2时所说的按权值大小排序,从最小的开始走。

最终版本

#include <iostream>
#include <stack>
#include <cstring>
#include <algorithm>using namespace std;/* 马踏棋盘 */typedef struct _horse
{int x;  //横坐标int y;  //纵坐标int s;  //下一步的方向int step;   //下一步的权值int flag;  //特殊点用
}HORSE;int chessboard[8][8];   //棋盘
int Next[8][2] = {{2,1}, {1,2}, {-1,2}, {-2,1}, {-2,-1}, {-1,-2}, {1,-2}, {2,-1}};  //方向
int cnt = 1;            //计数器
stack<HORSE> horse;//判别
bool judge(int a, int b)
{if(a < 0 || a > 7 || b < 0 || b > 7)    //边界return false;return true;
}//从小到大排序
bool cmp(HORSE& a, HORSE& b)
{return a.step < b.step;
}//计算权值
int steps(int a, int b)
{int sum = 0;for(int i = 0; i < 8; i++){int x = a + Next[i][0];int y = b + Next[i][1];if(judge(x,y) && chessboard[x][y] == 0)++sum;}return sum;
}//执行过程
void Horse(int x, int y)
{HORSE temp;int a,b;    //记录当前马位置附近的坐标chessboard[x][y] = cnt; //标记当前起始位置已被访问 temp.x = x; //记录当前马的位置temp.y = y;while(cnt < 64){int h_min = 8;      //权值最小的点int tx,ty,ti;       //记录权值最小的点的信息for(int i = 0; i < 8; i++){a = temp.x + Next[i][0];b = temp.y + Next[i][1];if(judge(a,b) && chessboard[a][b] == 0)     //判断{int step = steps(a,b);   //计算权值if(step < h_min)         //更新权值最小的点{h_min = step;    tx = a;ty = b;ti = i;}            }}//直接走权值最小的点chessboard[tx][ty] = ++cnt;temp.s = ti;//temp.step = h_min;horse.push(temp);memset(&temp, 0, sizeof(HORSE));temp.x = tx;temp.y = ty;}
}//特殊点执行过程(2,4)
void Horse_2(int x, int y)
{HORSE temp;HORSE horse_2[8];memset(horse_2, 0, sizeof(HORSE));int a,b;int flag = 0;   //记录该走那一个点了chessboard[x][y] = cnt;temp.x = x;temp.y = y;while(cnt < 64){int k = 0;for(int i = 0; i < 8; i++){a = temp.x + Next[i][0];b = temp.y + Next[i][1];if(judge(a,b) && chessboard[a][b] == 0)     //找出可走的点{int step = steps(a,b);horse_2[k].x = a;horse_2[k].y = b;horse_2[k].s = i;horse_2[k].step = step;++k;}}sort(horse_2, horse_2 + k, cmp);    //按权值从小到大排序for(int i = 0; i < k; i++)horse_2[i].flag = i;    if(k > 0 && flag < k)   //有路可走{chessboard[horse_2[flag].x][horse_2[flag].y] = ++cnt;temp.s = horse_2[flag].s;temp.step = horse_2[flag].step;temp.flag = horse_2[flag].flag;horse.push(temp);memset(&temp, 0, sizeof(HORSE));temp.x = horse_2[flag].x;temp.y = horse_2[flag].y;flag = 0;}else    //回溯{--cnt;chessboard[temp.x][temp.y] = 0;HORSE tt = horse.top();horse.pop();temp.x = tt.x;temp.y = tt.y;flag = tt.flag;++flag; //走下一个点}}
}//输出
void print()
{for(int i = 0; i < 8; i++){for(int j = 0; j < 8; j++)cout << chessboard[i][j] << ' ';cout << endl;}
}int main()
{int x,y;cout << "从那个点开始: ";cin >> x >> y;if(x == 2 && y == 4)Horse_2(x,y);elseHorse(x,y);print();return 0;
}

在这里插入图片描述

这篇关于马踏棋盘(从低效到高效)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/374137

相关文章

轻松上手MYSQL之JSON函数实现高效数据查询与操作

《轻松上手MYSQL之JSON函数实现高效数据查询与操作》:本文主要介绍轻松上手MYSQL之JSON函数实现高效数据查询与操作的相关资料,MySQL提供了多个JSON函数,用于处理和查询JSON数... 目录一、jsON_EXTRACT 提取指定数据二、JSON_UNQUOTE 取消双引号三、JSON_KE

Tomcat高效部署与性能优化方式

《Tomcat高效部署与性能优化方式》本文介绍了如何高效部署Tomcat并进行性能优化,以确保Web应用的稳定运行和高效响应,高效部署包括环境准备、安装Tomcat、配置Tomcat、部署应用和启动T... 目录Tomcat高效部署与性能优化一、引言二、Tomcat高效部署三、Tomcat性能优化总结Tom

Python利用自带模块实现屏幕像素高效操作

《Python利用自带模块实现屏幕像素高效操作》这篇文章主要为大家详细介绍了Python如何利用自带模块实现屏幕像素高效操作,文中的示例代码讲解详,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1、获取屏幕放缩比例2、获取屏幕指定坐标处像素颜色3、一个简单的使用案例4、总结1、获取屏幕放缩比例from

使用Python实现高效的端口扫描器

《使用Python实现高效的端口扫描器》在网络安全领域,端口扫描是一项基本而重要的技能,通过端口扫描,可以发现目标主机上开放的服务和端口,这对于安全评估、渗透测试等有着不可忽视的作用,本文将介绍如何使... 目录1. 端口扫描的基本原理2. 使用python实现端口扫描2.1 安装必要的库2.2 编写端口扫

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

在C#中获取端口号与系统信息的高效实践

《在C#中获取端口号与系统信息的高效实践》在现代软件开发中,尤其是系统管理、运维、监控和性能优化等场景中,了解计算机硬件和网络的状态至关重要,C#作为一种广泛应用的编程语言,提供了丰富的API来帮助开... 目录引言1. 获取端口号信息1.1 获取活动的 TCP 和 UDP 连接说明:应用场景:2. 获取硬

Python实现高效地读写大型文件

《Python实现高效地读写大型文件》Python如何读写的是大型文件,有没有什么方法来提高效率呢,这篇文章就来和大家聊聊如何在Python中高效地读写大型文件,需要的可以了解下... 目录一、逐行读取大型文件二、分块读取大型文件三、使用 mmap 模块进行内存映射文件操作(适用于大文件)四、使用 pand

高效管理你的Linux系统: Debian操作系统常用命令指南

《高效管理你的Linux系统:Debian操作系统常用命令指南》在Debian操作系统中,了解和掌握常用命令对于提高工作效率和系统管理至关重要,本文将详细介绍Debian的常用命令,帮助读者更好地使... Debian是一个流行的linux发行版,它以其稳定性、强大的软件包管理和丰富的社区资源而闻名。在使用

高效+灵活,万博智云全球发布AWS无代理跨云容灾方案!

摘要 近日,万博智云推出了基于AWS的无代理跨云容灾解决方案,并与拉丁美洲,中东,亚洲的合作伙伴面向全球开展了联合发布。这一方案以AWS应用环境为基础,将HyperBDR平台的高效、灵活和成本效益优势与无代理功能相结合,为全球企业带来实现了更便捷、经济的数据保护。 一、全球联合发布 9月2日,万博智云CEO Michael Wong在线上平台发布AWS无代理跨云容灾解决方案的阐述视频,介绍了

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设