问题描述
假设国际象棋盘有5*5共有25个格子。设计一个程序,使棋子从初始位置(棋盘格编号为1的位置)开始跳马,能够把棋盘的格子全部走一遍,每个格子只允许走一次。要求:1)输出一个解(用二维数组来记录跳马的过程,即[步号,棋盘编号],左上角为1步起点;2)求总共有多少解?*注:国际象棋的棋子是在格子中间的。国际象棋中的“马走日”,如下图所示,第一步为[1,1],第二步为[2,8]或者[2,12],第三步可以是[3,5]或[3,21],等,依次类推。

#include <cstdio>
const int n = 5;
int vis[n][n];
int path[n*n];
int dr[] = {-2, -1, 1, 2, 2, 1, -1, -2};	// 方向数组 
int dc[] = {1, 2, 2, 1, -1, -2, -2, -1};
int cnt = 0;	// 记录总共有多少种方案
void dfs(int r, int c, int step) {
	if(step==n*n) {	// 搜索完前部结点
		cnt++;	// 方案数加一
		if(cnt==1) {	// 只打印第一个中方案
			for(int i=0; i<n*n; i++) {
				printf("[%d,%d]\n", i+1, path[i]);
			}	
		}
	} else {
		for(int i=0; i<8; i++) {	// 尝试八个方向的邻居结点
			int newr = r + dr[i];	// 邻居结点 
			int newc = c + dc[i];
			if( 0<=newr && newr<n && 0<=newc && newc<n && vis[newr][newc]==0) {
				path[step] = newr * n + newc + 1;	// 当前结点的编号加入搜索路径 
				vis[newr][newc]=1;			// 标记访问 
				dfs(newr, newc, step+1); 
				vis[newr][newc]=0;	// 回溯后修改状态 
			} 
		}	
	}
}
int main() {
	path[0] = 1;	// 将第一个结点加入路径中
	vis[0][0] = 1;	// 标记第一个结点为访问过
	dfs(0, 0, 1);	// 开始dfs遍历
	printf("%d", cnt);
	return 0;
}


马走棋盘

相关文章: