骑士的旅行。
骑士可以每次走一个‘日’字,就像中国象棋里面的马。
给出一个 p*q 的棋盘,每个格子只能走一次,是否存在一种方法可以遍历整个棋盘。如果有多种方法输出字典序最小的。
关于此题中的字典序:
骑士每一次都会有八个方向可以选择,每一次都选择字典序小的来DFS。这样最终结果就是字典序最小的。
int jp[] = {-1, 1,-2, 2,-2, 2,-1, 1};
int jq[] = {-2,-2,-1,-1, 1, 1, 2, 2};
此为遍历时确定八个方向的数组。
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <queue> using namespace std; bool MarkDfs; int jp[] = {-1, 1,-2, 2,-2, 2,-1, 1}; int jq[] = {-2,-2,-1,-1, 1, 1, 2, 2}; int rp,rq,SumStep; struct P { int p,q; }path[1000]; bool MarkMap[30][30]; bool check() { int i,j; for(i = 1;i <= rp; ++i) { for(j = 1;j <= rq; ++j) { if(MarkMap[i][j] == false) return false; } } return true; } void dfs(int sp,int sq,int step) { if(MarkDfs == false) return ; MarkMap[sp][sq] = true; path[step].p = sp; path[step].q = sq; if(check()) { MarkDfs = false; SumStep = step; return ; } int tp,tq; for(int i = 0;i < 8; ++i) { tp = sp + jp[i]; tq = sq + jq[i]; if(tp >= 1 && tp <= rp && tq >= 1 && tq <= rq && MarkMap[tp][tq] == false) { dfs(tp,tq,step+1); } } MarkMap[sp][sq] = false; } int main() { int T,Case = 0; scanf("%d",&T); while(T--) { int i,j; scanf("%d %d",&rp,&rq); MarkDfs = true;; SumStep = 0; memset(MarkMap,false,sizeof(MarkMap)); for(i = 1;i <= rp && MarkDfs; ++i) { for(j = 1;j <= rq && MarkDfs; ++j) { dfs(i,j,0); } } printf("Scenario #%d:\n",++Case); if(MarkDfs == false) { for(i = 0;i <= SumStep; ++i) { printf("%c%d",path[i].q+'A'-1,path[i].p); } printf("\n"); } else { printf("impossible\n"); } printf("\n"); } return 0; }