洛谷P1747:象棋变种游戏中的最短路径探索-BFS算法实战解析
一、问题核心分析
这个"好奇怪的游戏"实际上是象棋的变种,我们需要计算两匹马从不同起点到达(1,1)位置的最少步数。特殊之处在于:
马不仅可以走"日"字(传统象棋走法)
还可以走"田"字(类似象的走法)
不能走到坐标≤0的位置
二、算法选择
广度优先搜索(BFS)是最佳选择,因为:
BFS天然适合寻找最短路径
棋盘规模不大(MAXN=50足够)
需要探索所有可能的移动方式
三、关键技术实现
移动方式定义:
传统马步:8种"日"字形走法
新增田步:4种"田"字形走法
共12种移动可能
BFS框架:
边界处理:
检查坐标是否越界(≤0或≥MAXN)
提前终止条件(startX=1且startY=1)
四、学习要点
五、优化空间
#include <iostream> #include <queue> #include <cstring> using namespACe std; const int MAXN = 50; const int dx[] = {-2,-2,-1,-1,1,1,2,2,-2,2,-2,2}; // 12种移动方式(8种马步+4种田步) const int dy[] = {-1,1,-2,2,-2,2,-1,1,-2,-2,2,2}; struct Point { int x, y, steps; }; int bfs(int startX, int startY) { if(startX == 1 && startY == 1) return 0; queue<Point> q; bool visited[MAXN][MAXN] = {false}; q.push({startX, startY, 0}); visited[startX][startY] = true; while(!q.empty()) { Point current = q.front(); q.pop(); for(int i = 0; i < 12; i++) { int nx = current.x + dx[i]; int ny = current.y + dy[i]; if(nx < 1 || ny < 1 || nx >= MAXN || ny >= MAXN) continue; if(visited[nx][ny]) continue; if(nx == 1 && ny == 1) { return current.steps + 1; } visited[nx][ny] = true; q.push({nx, ny, current.steps + 1}); } } return -1; // 理论上不会执行到这里 } int main() { int x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2; cout << bfs(x1, y1) << endl; cout << bfs(x2, y2) << endl; return 0; }
六、常见错误
忘记标记已访问节点导致无限循环
边界检查不完整导致数组越界
步数计数错误
通过这个案例,我们不仅学会了解决特定问题,更重要的是掌握了BFS算法在棋盘类问题中的应用模式,这种模式可以推广到许多类似场景中。
原创内容 转载请注明出处