例题:

POJ 1915 Knight Moves 骑士遍历问题(跳马问题)

在一个m*m的棋盘上,从任意一个给定的位置(sx , sy)出发,为象棋中的马找一条路通过最少的步数到达另一位置(ex ,ey),输出最少所需要的步数。

利用bfs求解。

当马在位置(x , y)的时候其后继节点(后继选择)是什么?

对于马,有八个方向可以选择,马可以跳到如下几个位置:

(x+2 , y+1) ,

(x+1 , y+2 ) ,

(x-1 , y+2) ,

(x-2 , y+1),

(x+2 , y -1) ,

(x+1 , y-2 ) ,

(x-1 , y-2) ,

(x-2 , y-1);

那么后继状态也就是这些可选的位置了。

当然要判断这些后继位置是否会越界,去掉那些会越界的节点。

Sample Input

3
8
0 0
7 0
100
0 0
30 50
10
1 1
1 1

Sample Output

5
28
0

/*Knight Moves*/
#include <iostream>
#include <cstdio>

using namespace std;

struct Node
{
int x ;
int y ;
int d ;
void init(int nx , int ny , int nd)
{
x = nx ;
y = ny ;
d = nd ;
}
};

bool visit[MAXN][MAXN];

int bfs(Node source , Node target){
queue<Node> Q ;
source.d = 0 ;
Q.push(source);
memset(visit , 0 , sizeof(visit)) ;
visit[source.x][source.y] = 1 ;
while(!Q.empty()){
Node a = Q.front() ;
Q.pop() ;
int x = a.x ;
int y = a.y ;
for(int i = 0 ; i < 8 ; i ++){
int nx = x + dir[i][0] ;
int ny = y + dir[i][1] ;
//判断新的节点是否会越界
if(nx < 0 || nx >= m || ny >= m || ny < 0)
continue ;
if(visit[nx][ny])
continue ;
//判断后继节点是否是目标节点
if(target.x == nx && target.y == ny)
return a.d + 1 ;
visit[nx][ny] = 1 ;
Node c ;
c.init(nx , ny , a.d + 1) ;
Q.push(c) ;
}
}
return -1 ;
}

//////////////////////////////////////////////////////////////////////////////////////////////

AC代码:

#include<iostream>
using namespace std;
const int Max = ; struct{
int r, c;
}sta, end, queue[Max * Max];
int len; bool vis[Max][Max];
int dr[] = {-, -, -, -, , , , };
int dc[] = {-, , -, , -, , -, }; bool inmap(int r, int c){
if(r >= && r < len && c >= && c < len)
return true;
return false;
} int main(){
int n;
cin >> n;
while(n --){
cin >> len;
cin >> sta.r >> sta.c >> end.r >> end.c;
if(sta.r == end.r && sta.c == end.c){ // 记得加起点等于终点的判断。
cout << '' << endl;
continue;
}
memset(vis, false, sizeof(vis));
vis[sta.r][sta.c] = true;
queue[].r = sta.r;
queue[].c = sta.c;
int head = , tail = , steps = ;
bool find = false;
while(!find){
steps ++;
int count = tail - head;
while(!find && count --){
for(int i = ; i < ; i ++){
int r = queue[head].r + dr[i];
int c = queue[head].c + dc[i];
if(r == end.r && c == end.c){
find = true;
break;
}
if(inmap(r, c) && !vis[r][c]){
vis[r][c] = true;
queue[tail].r = r;
queue[tail].c = c;
tail ++;
}
}
head ++; // 一开始把head++写到外面,卡了很久,以后要小心。
}
}
cout << steps << endl;
}
return ;
}

参考部分:

评价:

这份代码的优点很明显。相对与深度优先搜索来说,它只要每次访问一个层次,不会造成较大的空间浪费。

然后就是理解起来相对较为方便,只要搞清楚基本的思路和队列的用法,基本上磨磨蹭蹭的搞个几小时基本还是能够将结果返回出来的。

最新文章

  1. WCF学习之旅—TcpTrace工具(二十五)
  2. Python 常用模块之time&amp;datetime 和random
  3. 使用Django建立网站
  4. Scala映射
  5. 防止多次领取红包进行ID锁
  6. bzoj4418&amp;&amp;bzoj4419&amp;&amp;bzoj4420:SHOI2013Day2题解
  7. JS实现剪切板添加网站版权、来源
  8. hdu-----(4514)湫湫系列故事——设计风景线(树形DP+并查集)
  9. PHP 正则表达式常用函数使用小结
  10. IS about 64bit system
  11. WinDriver的一些
  12. PHP 表单验证 - 完成表单实例
  13. shell 变量说明
  14. 使用Nginx实现Tomcat集群负载均衡
  15. Win8 &amp; WP8.1 轻型数据库
  16. MySql日期与时间函数
  17. js二分算法排序
  18. Qt自定义滚动条(不使用样式表)
  19. vim 中:wq和:wq的不同之处
  20. LeetCode(83): 删除排序链表中的重复元素

热门文章

  1. Eclipse 打开当前文件所在的文件夹
  2. Spring MVC(二)
  3. Android编程获取手机的IMEI
  4. [!] Error installing AFNetworking
  5. 淘淘商城_day05_课堂笔记
  6. HDU 5831 Rikka with Parenthesis II
  7. POJ 2311 Cutting Game(SG+记忆化)
  8. VC中获取窗口控件相对客户区的坐标
  9. 多线程---优先级&amp;yield方法
  10. webservice整合spring cxf