分治法--马的Hamilton周游路线问题

1、问题描述


2、问题讲解

    在国际象棋中马是走日字的,如果是一般情况马一共有八种走法(如下图)

    

    所以我在这边用2个一位数组来表示其8种走法

    //考虑到马有8种走法
    int dx[8]={-2,-1,1,2,-2,-1,2,1};

    int dy[8]={-1,-2,-2,-1,1,2,1,2};

    之后就让马根据这八种走法来走不过还要考虑下面3种情况

    第一种情况

    如果马的下一步走法已经超出棋盘的范围了那么就不应该让马接下来走这一步转而去考虑其他的走法

    第二种情况

     如果马的下一步是已经走过的那么就不应该让马接下来走这一步转而去考虑其他的走法

    第三种情况

    如果马能够遍历完棋盘,那么就要考虑其最后一步是否可以通过上述的八种走法中的一种到达最开始的一步


    

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

    


猜你喜欢

转载自blog.csdn.net/qq_35654259/article/details/80644714
今日推荐