赞
踩
在N行N列的棋盘上,一位骑士按象棋中“马走日”的走法从初始坐标位置(Sx,Sy)出发,要求遍历(巡游)棋盘中每一个位置一次,请输出骑士巡游的位置顺序,或输出无解。
对于这个问题,我们可以用回溯法来处理。设骑士的当前坐标为q(x,y),则它的下一步的坐标可能为:
q(x+2,y+1) —— 右下走“日” (念ri,即竖着走)
q(x+1,y+2) —— 右下走“曰”(念yue,即横着走)
q(x-1,y+2) —— 右上走“曰”
q(x-2,y+1) —— 右上走“日”
q(x-2,y-1) —— 左上走“日”
q(x-1,y-2) —— 左上走“曰”
q(x+1,y-2) —— 左下走“曰”
q(x+2,y-1) —— 左下走“日”
由于骑士总是从坐标q(1,1)出发,因此可将骑士巡游的第一步固定为坐标q(1,1),其下一步由如上所述顺序依次试探,并且设以标记数组,用于标记每次试探的位置,若试探成功,则标记位置置为当前可行步数(即递归函数内的递归层数),若试探失败,则回溯至上一步。反复执行上述步骤,直至可行步数为n×n为止。
设一标记数组int m[n+1] [n+1](为方便计算,数组皆多开一个或一系空间),用于标记每次试探的位置,设一个二维数组next[9] [2]
用于计算下一步的试探坐标,设以整型变量step,用于记录可行步数,设以递归函数tour(int step,int x,int y),其函数返回类型为bool,当step=n×n+1时,表示巡游成功。
#include<iostream> #include<iomanip> using namespace std; const int n = 5; int m[n+1][n+1]; int next[9][2] = {{0,0},{2,1},{1,2},{-1,2},{-2,1},{-2,-1},{-1,-2},{1,-2},{2,-1}}; bool tour(int step,int x,int y){ if(step == n*n + 1) return true; bool q = false; for(int k = 1;k <= 8; k++){ int u = x + next[k][0]; int v = y + next[k][1]; if(u >= 1 && u <= n && v >= 1 && v <= n){ if(!m[u][v]){ m[u][v] = step; q = tour(step + 1,u,v); if(!q) m[u][v] = 0; } } } return q; } int main(){ m[1][1] = 1; if(tour(2,1,1)){ for(int i = 1;i <= n; i++){ for(int j = 1; j <= n; j++) cout << setw(4) << m[i][j]; cout << endl; } } else cout << "no solution" << endl; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。