假设国际象棋棋盘有5*5共25个格子。设计一个程序,使棋子从初始位置(如图)开始跳马,需要将棋盘的格子全部都走一遍,每个格子只允许走一次。
问:总共有多少解。(提示:回溯法)
P.S国际象棋的棋子是在格子中间的。国际象棋中的“马走日”,如第一步为[1,1],第二步为[2,8]或[2,12],第三步可以是[3,5]或[3,21]等,以此类推。
#include <iostream>
using namespace std;
const int m = 5, n = 5;
int countN = 0;
int trace[m][n] = { 0 };
int changedir[][2] = { {1,2},{2,1},{1,-2},{2,-1},{-1,2},{-2,1},{-1,-2},{-2,-1} };
void printT()
{
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
cout << trace[i][j] << ' ';
}
cout << endl;
}
cout << "------------" << endl;
}
void visit(int x, int y, int step)
{
trace[x][y] = step;
//printT();
if (m*n == step)
{
countN++;
printT();
return;
}
int nextx, nexty;
for (int i = 0; i < 8; i++)
{
nextx = x + changedir[i][0];
nexty = y + changedir[i][1];
if (nextx < 0 || nextx>(m-1) || nexty < 0 || nexty>(n-1)|| trace[nextx][nexty]!=0)
{
continue;
}
visit(nextx, nexty, step + 1);
trace[nextx][nexty] = 0;
}
}
void main()
{
int firstX , firstY ;
cout << "输入起始位置(棋盘的左上角编号位置(0,0)):" << endl;
cin >> firstX >> firstY;
//printT();
visit(firstX, firstY, 1);
cout << "Count " << countN << endl;
}
思考:此题也是递归回溯的思想。当确定一个位置之后,要考虑8种可以跳马的方向,设置一个记步数的变量step,当step为25时退出递归,同时把最后确定的一个位置,即写着25的格子的变量重置为0,同时退回到第24步,去寻找其它第25步的可能位置。
结果: