在n*m的棋盘中,马只能走“日” 字。马从位置(x,y)处出发,把棋盘的每一格都走一次,且只走一次。找出所有路径。

×××××××××××××

类似问题:

在半个中国象棋棋盘上,马在左下角(1,1)处,马走日字…而且只能往右走…不能向左…可上可下…求从起点到(m, n)处有几种不同的走法。

八皇后。

×××××××××××××

预备知识---》图的深度优先:

https://www.cnblogs.com/OctoptusLian/p/8260173.html

参考代码1:

https://blog.csdn.net/skylv111/article/details/38930213

参考代码2(优先):

https://blog.csdn.net/qq_35654259/article/details/80644714

参考思考(图例):

https://blog.csdn.net/crayondeng/article/details/17174951

java版本:

https://maozj.iteye.com/blog/671911

***Hanmilton路径 主代码,不需要回到远点的请删除相关部分。8*8的国际象棋棋盘上的一只马,恰好走过除起点外的其他63个位置各一次,最后回到起点,这条路线称为马的一条Hamilton周游路线。对于给定的m*n的国际象棋棋盘,m和n均为大于5的偶数,且|m-n|≤2,试设计一个分治算法找出马的一条Hamilton周游路线。

#include<stdio.h>
#include<stdlib.h>
#define max 101 int m,n;//棋盘大小
int start_x,start_y;//起点位置
int dx[]={-,-,,,-,-,,};
int dy[]={-,-,-,-,,,,};
int board[max][max]={}; int finish(int x,int y)
{//判断是否是死路
if(x< || y< || x>m || y>n || board[x][y]!=)
return ;
else
return ;
}
int next_move(int x,int y)
{//判断下一步能否回到起点
for(int i=;i<;i++)
if(x+dx[i]==start_x && y+dy[i]==start_y)
return ;
return ;
}
void show(int n,int m)
{//输出路线
for(int i=;i<=m;i++) {
for(int j=;j<=n;j++)
printf("%3d",board[i][j]);
printf("\n");
}
}
void move(int x,int y,int num)
{
if(num==n*m && next_move(x,y)) {
show(n,m);
exit();
}
for(int i=;i<;i++) {
int next_x=x+dx[i];
int next_y=y+dy[i];
if(finish(next_x,next_y)) {
board[next_x][next_y]=num+;
move(next_x,next_y,num+);
board[next_x][next_y]=;
}
}
}
int main()
{
printf("请输入棋盘的行数和列数:\n");
scanf("%d%d",&m,&n);
printf("请输入起始坐标:\n");
scanf("%d%d",&start_x,&start_y);
board[start_x][start_y]=;
int number=;
printf("马的周游路线为:\n");
move(start_x,start_y,number);
return ;
}
//辅助理解
#include <stdio.h>
#include <stdlib.h>
#include <iostream> using namespace std; #define max 101 int count = ;
int m,n;//棋盘大小
int start_x,start_y;//起点位置
//考虑到马有8种走法
int dx[]={-,-,,,-,-,,};
int dy[]={-,-,-,-,,,,};
int board[max][max]={}; //输出棋盘
void show(int m,int n){
for(int i = ;i<m;i++){
for(int j = ;j<n;j++){
cout<<board[i][j]<<" ";
}
cout<<endl;
}
}
//判断下一步是否是起始的位置
int next_move(int x,int y){
for(int i = ;i<;i++){
if(board[x+dx[i]][y+dy[i]] == ){//1表示马的起始位置
return ;
}
}
return ;
}
//判断是否填了
int finish(int x,int y){
if(board[x][y] == ){//0表示马没有走过 非0表示马已经走过
return ;
}
return ;
}
//马的下一步走法已经超出棋盘的范围了
int judge(int x,int y,int m,int n){
if(x>=&&x<m&&y>=&&y<n){
return ;
}
return ;
}
//马走的函数
void move(int x,int y,int num){
if(num == m*n+&&next_move(x,y)){
cout<<++count<<endl;
show(m,n);//输出棋盘
cout<<endl;
return ;
}else{
for(int i = ;i<;i++){
if(finish(x+dx[i],y+dy[i])&&judge(x+dx[i],y+dy[i],m,n)){//若不符合上述条件就表示马放弃之后会走这一步了
board[x+dx[i]][y+dy[i]] = num;//在棋盘上记录马的步数
move(x+dx[i],y+dy[i],num+);
board[x+dx[i]][y+dy[i]] = ;//当遍历完棋盘后将棋盘重新置为0(表示马为走过) (不过开始位置还是1这里读者慢慢体会)
}
}
}
} int main(){
cout<<"请输入格子数"<<endl;
cin>>m>>n;
cout<<"请输入起始的位置"<<endl;
cin>>start_x>>start_y;
int number = ;
board[start_x][start_y] = number;//将起始位置为1 move(start_x,start_y,number+);
cout<<count;
}
//上面的如果还理解不了,可以看这个。
#include <stdio.h>
#include <string.h>
int matrix[][];
int journey = ;
int step_x[]={,,,,-,-,-,-},step_y[]={,,-,-,-,-,,}; void outMatrix(){
int i,j;
for (i=;i<;i++)
{
for (j=;j<;j++)
{
printf("%-2d ",matrix[i][j]);
}
printf("\n");
}
} bool outofbounds(int x,int y){
return x < || y < || x >= || y >= ;
} bool isCome(int x,int y){
return matrix[x][y];
} void gotoend(int x, int y ){
if(journey>) return;
int i;
matrix[x][y]=journey++; //当前是第几步
for (i = ;i<;i++)
{
int next_x = x+step_x[i];
int next_y = y+step_y[i];
if(!outofbounds(next_x,next_y) && !matrix[next_x][next_y]){ gotoend(next_x,next_y);
}
}
} int main(){
int start_x,start_y;
int i;
scanf("%d%d",&start_x,&start_y);
for (i = ;i<;i++) {
memset(matrix[i],,sizeof(matrix[]));
}
gotoend(start_x,start_y);
outMatrix();
return ;
}
//这个还有问题
    package test;  

    /**
* create on 2010.05.21 TODO 回溯算法
*
* @author 毛正吉
* @version v1.0
*
*/
public class RecollectionSearch { /**
* @param args
*/
public static void main(String[] args) {
// 注意(0<=x<n && 0<=y<m)
int n = 5;
int m = 4;
int x = 0;
int y = 0;
RecollectionSearch rs = new RecollectionSearch(n, m, x, y);
rs.find(x, y, 2);
System.out.println("######################");
System.out.println("总解数count=" + rs.getCount());
System.out.println("######################"); } // 棋盘行数
private int n;
// 棋盘列数
private int m;
// 马的起始x坐标
private int x;
// 马的起始y坐标
private int y;
// 棋盘坐标
private int[][] a;
// 求解总数
private int count;
// "日"子x坐标
public int[] fx = { 1, 2, 2, 1, -1, -2, -2, -1 };
// "日"子y坐标
public int[] fy = { 2, 1, -1, -2, -2, -1, 1, 2 }; /**
* 构造方法
*
* @param _n
* @param _m
* @param _x
* @param _y
*/
public RecollectionSearch(int _n, int _m, int _x, int _y) {
n = _n;
m = _m;
x = _x;
y = _y;
a = new int[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
a[i][j] = 0;
}
}
// 马的起点
a[x][y] = 1;
count = 0;
} public void find(int x, int y, int dep) {
int i, xx, yy;
for (i = 0; i < 7; i++) {
xx = x + fx[i];
yy = y + fy[i];
// 判断新坐标是否出界,是否已走过
if (check(xx, yy) == 1) {
a[xx][yy] = dep;
if (dep == n * m) {
output();
} else {
// 从新坐标出发,递归下一层
find(xx, yy, dep + 1);
}
// 回溯,恢复未走标志
a[xx][yy] = 0;
}
}
} /**
* 判断新坐标是否出界,是否已走过
*
* @param xx
* @param yy
* @return
*/
public int check(int xx, int yy) {
if (xx >= n || yy >= m || xx < 0 || yy < 0 || a[xx][yy] != 0) {
return 0;
}
return 1;
} /**
* 输出结果
*/
public void output() {
count++;
System.out.println("count=" + count);
for (int y = 0; y < n; y++) {
System.out.println("");
for (int x = 0; x < m; x++) {
System.out.print(a[y][x] + " ");
}
}
System.out.println("");
} public int getN() {
return n;
} public void setN(int n) {
this.n = n;
} public int getM() {
return m;
} public void setM(int m) {
this.m = m;
} public int getCount() {
return count;
} public void setCount(int count) {
this.count = count;
} public int getX() {
return x;
} public void setX(int x) {
this.x = x;
} public int getY() {
return y;
} public void setY(int y) {
this.y = y;
}
}

【算法】深度优先 马走日 Hamilton routes的更多相关文章

  1. noi 8465 马走日

    8465:马走日 查看 提交 统计 提问 总时间限制:  1000ms 内存限制:  1024kB 描述 马在中国象棋以日字形规则移动. 请编写一段程序,给定n*m大小的棋盘,以及马的初始位置(x,y ...

  2. Problem L: 搜索基础之马走日

    Problem L: 搜索基础之马走日 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 134  Solved: 91[Submit][Status][W ...

  3. 小米 oj 马走日 (bfs 或 双向bfs)

     马走日 序号:#56难度:困难时间限制:1500ms内存限制:10M 描述 在中国象棋中,马只能走日字型.现在给出一个由 N*M 个格子组成的中国象棋棋盘( 有(N+1)*(M+1)个交叉点可以落子 ...

  4. T1219:马走日

    [题目描述] 马在中国象棋以日字形规则移动. 请编写一段程序,给定n×m大小的棋盘,以及马的初始位置(x,y),要求不能重复经过棋盘上的同一个点,计算马可以有多少途径遍历棋盘上的所有点. [输入] 第 ...

  5. 马走日的解法(dfs)

    马在中国象棋以日字形规则移动. 请编写一段程序,给定n*m大小的棋盘,以及马的初始位置(x,y),要求不能重复经过棋盘上的同一个点,计算马可以有多少途径遍历棋盘上的所有点. Input 第一行为整数T ...

  6. Knight's Trip---hdu3766(马走日求最小走的步数)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3766 给你一个x ,y 求出从(0,0)位置到达需要的最小步数每次只能走日型: 下图为暴力bfs得到的 ...

  7. [openjudge-搜索]深度优先搜索之马走日

    题目描述 描述 马在中国象棋以日字形规则移动.请编写一段程序,给定n*m大小的棋盘,以及马的初始位置(x,y),要求不能重复经过棋盘上的同一个点,计算马可以有多少途径遍历棋盘上的所有点. 输入 第一行 ...

  8. NOI2.5 8465:马走日

    描述 马在中国象棋以日字形规则移动. 请编写一段程序,给定n*m大小的棋盘,以及马的初始位置(x,y),要求不能重复经过棋盘上的同一个点,计算马可以有多少途径遍历棋盘上的所有点. 输入 第一行为整数T ...

  9. openjudge8465:马走日 [搜索]

    描述 马在中国象棋以日字形规则移动. 请编写一段程序,给定n*m大小的棋盘,以及马的初始位置(x,y),要求不能重复经过棋盘上的同一个点,计算马可以有多少途径遍历棋盘上的所有点. 输入 第一行为整数T ...

随机推荐

  1. 【Linux篇】--sed的用法

    一.前述 Sed是一种流编辑器,它是文本处理中非常中的工具,能够完美的配合正则表达式使用,功能不同凡响.处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用 ...

  2. nginx.conf添加lua.conf配置

    1.在nginx的conf下配置lua.conf......vi lua.conf server { listen ; server_name _; location /lua { default_t ...

  3. T4模板简单了解

    T4模板基础 T4即为Text Template Transformation Toolkit,一种可以由自己去自定义规则的代码生成器.根据业务模型可生成任何形式的文本文件或供程序调用的字符串 在VS ...

  4. Python爬虫实例:爬取B站《工作细胞》短评——异步加载信息的爬取

    很多网页的信息都是通过异步加载的,本文就举例讨论下此类网页的抓取. <工作细胞>最近比较火,bilibili 上目前的短评已经有17000多条. 先看分析下页面 右边 li 标签中的就是短 ...

  5. 纯CSS打造淘宝导航菜单栏

    店铺装修-PC端-基础页-首页-装修页面:编辑“菜单”模块-显示设置,粘贴如下CSS: /* 导航条背景色*/ .skin-box-bd .menu-list{background: none rep ...

  6. mysql 设置自增主键id的起始值

    修改user表,主键自增从20000开始 alter table user AUTO_INCREMENT=20000;

  7. Android远程桌面助手(B1185)for Android P开发者预览版

    Android P的开发者预览版已出,其中App compatibility changes部分特别强调“The platform restricts the use of some non-SDK ...

  8. Android设计模式总结

    1.复合模式:三层架构.MVC.MVP.MVVM 2.设计模式-单例模式 配置类的使用. 3.设计模式-模板方法 通过抽象类或接口提前定义要实现的方法. 4.设计模式-观察者模式 消息的通知. 5.设 ...

  9. Spring AOP 整理笔记

    一.AOP概念 AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. 利用AOP可以对业务逻辑的各 ...

  10. .NET Core 学习笔记2——管理nuget包

    .NET Core 基于Nuget包.它是一个.nupkg后缀的zip文件. 工具 dotnet 工具 vs2017 的程序包管理控台 这两个工具都可以用命令行来下载安装,更新,上传包(上传要先在网站 ...