騎士棋盤遍歷
描述
如下圖分別是(p,q)爲(3,9) , (6,3) ,以及(5,5)的棋盤空間。
請問對於每一種棋盤(p,q),請問2D騎士是否有一種一次遍歷所有棋盤方格的路線?
如果有,請輸出這條路線(若有多條路線,請輸出字典序最小的路線)。
如果沒有,請輸出無。
輸入
輸入數據第一行爲正整數n,代表有多少組輸入樣例
接下來n行是兩個整數代表行p和列q, 代表變形棋盤的行列參數,其中(1 <= p * q <= 26)。
輸出
每個樣例的輸出2行,格式如下:
“#i:” 其中i代表第i種棋盤
騎士跳過的每個格子(每個訪問的格子用大寫字母加數字表示),一條可行的路徑輸出如(A1B3C1A2B4C2A3B1C3A4B2C4),
如果沒有可行方案,則第二行輸出:none
樣例
5
5 1
5 2
5 3
5 4
5 5
#1:
none
#2:
none
#3:
none
#4:
A1B3A5C6D4B5D6C4D2B1A3C2B4A2C1D3B2D1C3D5B6A4C5A6
難度
高,馬踏棋盤問題,可以用回溯,也可以用DFS
代碼
code by linli
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define MAXN 30
struct Point{
int r,c;
};
Point path[30]; //用於存儲路徑
int p,q;//棋盤參數
int visit[MAXN][MAXN];//標記矩陣
int direction[8][2]={{-2,-1},{-2,1},{-1,-2},{-1,2},{1,-2},{1,2},{2,-1},{2,1}};
bool DFS(int x, int y, int step){ //行,列,當前步數
if(step==p*q)//搜索成功
return true;
if(x<0||x>=p||y<0||y>=q||visit[x][y]) //超過邊界或訪問過了
return false;
visit[x][y]=1;//標記該點
path[step].r = x;
path[step].c = y;
for(int i=0;i<8;i++){ //遍歷鄰居節點
int nx=x+direction[i][0]; //擴展狀態座標
int ny=y+direction[i][1];
if(DFS(nx,ny,step+1)){
return true;
}
}
visit[x][y]=0; //回溯,取消這一步的走法
return false;
}
int main(){
int n,flag;
cin>>n;
int caseNumber=0;
while(n--){
flag = 0;
cin>>p>>q; //行p,列q
memset(visit,0,sizeof(visit));
cout<<"#"<<++caseNumber<<":"<<endl;
int i;
for(i=0;i<q;i++)
for(int j=0;j<p;j++){
if(DFS(i,j,0)){
flag=1;
for(int k=0;k<p*q;k++)
cout<<char(path[k].r+'A')<<(path[k].c+1);
break;
}
}
if(flag) break;
else cout<<"none"<<endl;
}
return 0;
}
//#4:
//A1B3A5C6D4B5D6C4D2B1A3C2B4A2C1D3B2D1C3D5B6A4C5A6
//A1B3C1A2B4D3E1C2D4E2C3A4B2D1E3C4A3B1D2E4
得到的順序有點問題…
code by Andy