poj 2488 A Knight's Journey 【骑士周游 dfs + 记忆路径】
题目地址:http://poj.org/problem?id=2488
Sample Input
3 1 1 2 3 4 3
Sample Output
Scenario #1: A1 Scenario #2: impossible Scenario #3: A1B3C1A2B4C2A3B1C3A4B2C4
题目:给你一个p*q的棋盘,规则布局参考上图。列用字母表示,行用数字表示。这样一个左上角的节点就是(A,1)。
骑士的棋子走日字形状,可以从任意节点出发,终点也是任意的。问你能不能遍历所有的位置,并输出这样的路径,如果
存在多条路径,输出字典序最小的那条路径。
分析:按照上面那个图片的提示,从当前位置出发遍历8个方向,如果最后能到达,得到的就是字典序最小的序列。
起点一定会是(A1)。直接从A1开始dfs。
通过这道题,再次体会到回溯的地方。。。。。。
code:
#include<stdio.h> #include<string.h> #include <queue> #include <stack> #include <algorithm> #define Max 21 using namespace std; int n, m; bool vis[30][30]; int x[]={-1, 1, -2, 2,-2, 2,-1, 1}; int y[]={-2,-2, -1,-1, 1, 1, 2, 2}; //从当前马的位置可以走到的8个位置 //在满足字典序最小的前提下 这8个方向的遍历先后不能变动 bool ok; struct node { int col, row; }path[1000]; int e=0; bool sure(int i, int j) { if(i>=1 && i<=n && j>=1 && j<=m) return true; else return false; } void dfs(int i, int j, int cnt)//cnt表示我们在当前这次dfs偶中搜索到的节点 { path[cnt].col=j; path[cnt].row=i;//当前位置进入路径队列 if(cnt==n*m){ ok=true; return; //所有节点都已经遍历到 }//在这return 开始往回回溯 int a, b; for(int k=0; k<8; k++){ a=i+x[k]; b=j+y[k]; if(sure(a, b) && !vis[a][b]){ vis[a][b]=true; dfs(a, b, cnt+1); if(ok==true) return;//在这return 返回主函数 vis[a][b]=false; } } return; } int main() { int tg; scanf("%d", &tg); int cnt=1; while(tg--) { scanf("%d %d", &n, &m); ok=false; if(n==1 && m==1){ printf("Scenario #%d:\n", cnt++); printf("A1\n\n"); continue; } else{ ok=false; memset(vis, false, sizeof(vis)); vis[1][1]=true; e=0; dfs(1, 1, 1); if(!ok){ printf("Scenario #%d:\n", cnt++); printf("impossible\n\n"); } else{ printf("Scenario #%d:\n", cnt++); for(int i=1; i<=n*m; i++) { printf("%c%d", path[i].col+'A'-1, path[i].row ); } printf("\n\n"); } } } return 0; }