ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

【跳马问题】“回溯法”——《算法设计与分析(第五版)》

2022-01-15 18:33:49  阅读:226  来源: 互联网

标签:++ chessBoard 跳马 int 回溯 meansMove auxiliaryBoard 第五版


文章目录


一、算法要求

问题描述:在 N*N 棋盘上有 N^2个格子,马在初始位置(X0,Y0),按照象棋中马走“日” 的规则,
使马走遍全部格子且每个格子仅经过一次。编程输出马的走法。
编程实现,给出 N=5,(X0,Y0)=(1,1)时的运行结果。

1. 思路

有许多问题,当需要找出它的解集或者要求回答什么解是满足某些约束条件的最佳解时,往往要使用回溯法。
回溯法的基本做法是搜索,或是一种组织得井井有条的,能避免不必要搜索的穷举式搜索法。这种方法适用于解一些组合数相当大的问题。
回溯法在问题的解空间树中,按深度优先策略,从根结点出发搜索解空间树。
算法搜索至解空间树的任意一点时,先判断该结点是否包含问题的解。如果肯定不包含,则跳过对该结点为根的子树的搜索,逐层向其祖先结点回溯;否则,进入该子树,继续按深度优先策略搜索。


二、完整代码

1. 主文件

main.cpp:

// Project4_2: 用回溯法求解跳马问题

#include"Improve2.h"

int main() {

	//初始数据
	const int lengthBoard = 5,
		begingX = 1,
		begingY = 1;

	//打印初始数据
	cout << "#The initial data are as follows: \n"
		<< "\tLength of the chessboard: " << lengthBoard << endl
		<< "\tInitial coordinates: ( " << begingX << " , " << begingY << " )" << endl;

	Console();
	// 调用回溯函数 
	Backtracking(auxiliaryX, auxiliaryY);						
	// 打印方法数量
	cout << "#The number of possible methods in total is: "
		<< countMethod << endl;

	return 0;
}


2. 头文件

Improve2.h:

#pragma once
#ifndef __IMPROVE2__
#define __IMPROVE2__

#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;

//初始数据
const int lengthBoard = 5,
	begingX = 1,
	begingY = 1;


int countStep = 0, 			// 标记第几步
	countMethod = 1;		// 标记这是第几种可能的输出 
const int auxiliaryBoard = lengthBoard + 4,
	auxiliaryX = begingX + 1,
	auxiliaryY = begingY + 1;

int meansMove[8][2],		// 保存八种走法
	chessBoard[auxiliaryBoard][auxiliaryBoard];		// 棋盘 

void Console() {

	//初始化棋盘
	int i, j;
	for (i = 0; i < 2; i++) {//up
		for (j = 0; j < auxiliaryBoard; j++) {
			chessBoard[i][j] = -1;
		}
	}
	for (i = auxiliaryBoard - 2; i < auxiliaryBoard; i++) {//down
		for (j = 0; j < auxiliaryBoard; j++) {
			chessBoard[i][j] = -1;
		}
	}
	for (i = 0; i < auxiliaryBoard; i++) {//left
		for (j = 0; j < 2; j++) {
			chessBoard[i][j] = -1;
		}
	}
	for (i = 0; i < auxiliaryBoard; i++) {//right
		for (j = auxiliaryBoard - 2; j < auxiliaryBoard; j++) {
			chessBoard[i][j] = -1;
		}
	}
	for (i = 2; i < auxiliaryBoard - 2; i++) {//inside
		for (j = 2; j < auxiliaryBoard - 2; j++) {
			chessBoard[i][j] = 0;
		}
	}

	//初始化八种走法meansMove[x][y]
	meansMove[0][0] = 2; 	meansMove[0][1] = 1;		// {x+2,y+1}
	meansMove[1][0] = 1;	meansMove[1][1] = 2;		// {x+1,y+2}
	meansMove[2][0] = -1;	meansMove[2][1] = 2;		// {x-1,y+2}
	meansMove[3][0] = -2;	meansMove[3][1] = 1;		// {x-2,y+1}
	meansMove[4][0] = -2;	meansMove[4][1] = -1;		// {x-2,y-1}
	meansMove[5][0] = -1;	meansMove[5][1] = -2;		// {x-1,y-2}
	meansMove[6][0] = 1;  	meansMove[6][1] = -2;		// {x+1,y-2}	
	meansMove[7][0] = 2;    meansMove[7][1] = -1;		// {x+2,y-1}

	chessBoard[auxiliaryX][auxiliaryY] = ++countStep;	// 初始步数 
	
}

// 打印棋盘 
void Display() {
	cout << "\n#The following is a simple situation: " << endl;
	for (int i = 2; i < auxiliaryBoard - 2; i++) {
		for (int n = 0; n < lengthBoard; n++)
			cout << "+--";
		cout << "+" << endl;

		for (int j = 2; j < auxiliaryBoard - 2; j++) {
			if (chessBoard[i][j] < auxiliaryBoard - 2)
				cout << "|" << setw(2) << chessBoard[i][j] ;
			else
				cout << "|" << setw(2) << chessBoard[i][j] ;
		}
		cout << "|" << endl;
	}
	for (int m = 0; m < lengthBoard; m++)
		cout << "+--";
	cout << "+\n" << endl;
}

// 跳马回溯函数
void Backtracking(int x, int y) {
	if (countStep == (lengthBoard*lengthBoard)) {//终止条件
		countMethod++;
		if (countMethod == 2) {
			Display();
		}
	}

	int i;
	for (i = 0; i < 8; i++) {						// 8种可能跑法 
		// 计算准备要走的这一步的位置
		int a = x + meansMove[i][0];
		int b = y + meansMove[i][1];
		if (chessBoard[a][b] == 0) {				// 能走 
			chessBoard[a][b] = ++countStep;			// 标记 
			Backtracking(a, b);						// 向下走 
			chessBoard[a][b] = 0;					// 退回来,还原状态 
			countStep--; 							// 对称处理 
		}
	}
}

#endif


3. 效果展示

在这里插入图片描述


三、补充

回溯算法效率
问题的解向量:回溯法希望一个问题的解能够表示成一个n元式(x1,x2,…,xn)的形式。
显约束:对分量xi的取值限定。
隐约束:为满足问题的解而对不同分量之间施加的约束。
解空间:对于问题的一个实例,解向量满足显式约束条件的所有多元组,构成了该实例的一个解空间。

注意:同一个问题可以有多种表示,有些表示方法更简单,所需表示的状态空间更小(存储量少,搜索方法简单)。

文档供本人学习笔记使用,仅供参考。

标签:++,chessBoard,跳马,int,回溯,meansMove,auxiliaryBoard,第五版
来源: https://blog.csdn.net/m0_46895048/article/details/122513719

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有