zoukankan      html  css  js  c++  java
  • 【算法】深度优先 马走日 Hamilton routes

     在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("
    ");
        }        
    }
    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("请输入棋盘的行数和列数:
    ");
        scanf("%d%d",&m,&n);
        printf("请输入起始坐标:
    ");
        scanf("%d%d",&start_x,&start_y);
        board[start_x][start_y]=1;
        int number=1;
        printf("马的周游路线为:
    ");
        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(" "); } } 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;  
            }  
        }  
  • 相关阅读:
    docker使用以及dockerfile编写
    c++:空构造空析构的益处之一
    python os.path模块常用方法详解(转)
    enlarge your dataset
    解决镜像无法删除的问题multiple repositories
    Ubuntu 14.04 LTS 安装Docker(转)
    忘记root密码,怎么办
    [Unity3D]降低向Shader中传值的开销
    Shader预处理宏、内置状态变量、多版本编译等
    Unity Shader 常用函数列表
  • 原文地址:https://www.cnblogs.com/paprikatree/p/10530075.html
Copyright © 2011-2022 走看看