首页 > 技术文章 > 【算法】深度优先 马走日 Hamilton routes

paprikatree 2019-03-14 14:25 原文

 在nm的棋盘中,马只能走“日” 字。马从位置(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[8]={-2,-1,1,2,-2,-1,2,1};
int dy[8]={-1,-2,-2,-1,1,2,1,2};
int board[max][max]={0};
 
int finish(int x,int y)
{//判断是否是死路 
    if(x<1 || y<1 || x>m || y>n || board[x][y]!=0)
        return 0;
    else
        return 1;
}
int next_move(int x,int y)
{//判断下一步能否回到起点 
    for(int i=0;i<8;i++)
        if(x+dx[i]==start_x && y+dy[i]==start_y) 
            return 1;
    return 0;
}
void show(int n,int m)
{//输出路线 
    for(int i=1;i<=m;i++) {
        for(int j=1;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(1);
    }
    for(int i=0;i<8;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+1;
            move(next_x,next_y,num+1);
            board[next_x][next_y]=0;
        }
    }
}
int main()
{
    printf("请输入棋盘的行数和列数:\n");
    scanf("%d%d",&m,&n);
    printf("请输入起始坐标:\n");
    scanf("%d%d",&start_x,&start_y);
    board[start_x][start_y]=1;
    int number=1;
    printf("马的周游路线为:\n");
    move(start_x,start_y,number);
    return 0;
} 

 

 

//辅助理解
#include <stdio.h> #include <stdlib.h> #include <iostream> using namespace std; #define max 101 int count = 0; int m,n;//棋盘大小 int start_x,start_y;//起点位置 //考虑到马有8种走法 int dx[8]={-2,-1,1,2,-2,-1,2,1}; int dy[8]={-1,-2,-2,-1,1,2,1,2}; int board[max][max]={0}; //输出棋盘 void show(int m,int n){ for(int i = 0;i<m;i++){ for(int j = 0;j<n;j++){ cout<<board[i][j]<<" "; } cout<<endl; } } //判断下一步是否是起始的位置 int next_move(int x,int y){ for(int i = 0;i<8;i++){ if(board[x+dx[i]][y+dy[i]] == 1){//1表示马的起始位置 return 1; } } return 0; } //判断是否填了 int finish(int x,int y){ if(board[x][y] == 0){//0表示马没有走过 非0表示马已经走过 return 1; } return 0; } //马的下一步走法已经超出棋盘的范围了 int judge(int x,int y,int m,int n){ if(x>=0&&x<m&&y>=0&&y<n){ return 1; } return 0; } //马走的函数 void move(int x,int y,int num){ if(num == m*n+1&&next_move(x,y)){ cout<<++count<<endl; show(m,n);//输出棋盘 cout<<endl; return ; }else{ for(int i = 0;i<8;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+1); board[x+dx[i]][y+dy[i]] = 0;//当遍历完棋盘后将棋盘重新置为0(表示马为走过) (不过开始位置还是1这里读者慢慢体会) } } } } int main(){ cout<<"请输入格子数"<<endl; cin>>m>>n; cout<<"请输入起始的位置"<<endl; cin>>start_x>>start_y; int number = 1; board[start_x][start_y] = number;//将起始位置为1 move(start_x,start_y,number+1); cout<<count; }

 

//上面的如果还理解不了,可以看这个。
#include <stdio.h>
#include <string.h> int matrix[10][9]; int journey = 1; int step_x[]={1,2,2,1,-1,-2,-2,-1},step_y[]={2,1,-1,-2,-2,-1,1,2}; void outMatrix(){ int i,j; for (i=0;i<10;i++) { for (j=0;j<9;j++) { printf("%-2d ",matrix[i][j]); } printf("\n"); } } bool outofbounds(int x,int y){ return x < 0 || y < 0 || x >= 10 || y >= 9; } bool isCome(int x,int y){ return matrix[x][y]; } void gotoend(int x, int y ){ if(journey>90) return; int i; matrix[x][y]=journey++; //当前是第几步 for (i = 0;i<8;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 = 0;i<10;i++) { memset(matrix[i],0,sizeof(matrix[0])); } gotoend(start_x,start_y); outMatrix(); return 0; }
//这个还有问题

 

    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;  
        }  
    }  

 

推荐阅读