Knight Moves poj-1915
题目大意:在国际象棋中有一个骑士,想从一个点到达另一个点。骑士可以从2*3的矩阵的一角跳到对角线的另一角。问:骑士最少需要跳多少次才能从一个点跳到另一个点。
注释:棋盘大小l为1<=l<=300.
想法:显然,这是一道非常经典的宽度优先搜索的题目(bfs)。我们通过起始点开始宽搜:对于当前点来讲,我们通过数组记录骑士可以到达的8个方向,并且判断骑士向每个方向跳跃是否仍然在棋盘内。如果骑士到达了当前点,我们将当前点标记为true。显然,如果后来骑士跳跃到了一个已经被标记过的点,显然是要相较于之前的枚举更加差的。紧接着,我们维护一个数组ans[i][j]表示从起始点到(i,j)需要的步数。最后,我们只需要输出答案即可。
最后,附上丑陋的代码... ...
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 #include <algorithm> 6 using namespace std; 7 int map[350][350]; 8 int ans[350][350]; 9 int n; 10 int sx,sy,ex,ey; 11 int a[8][2]= {1,2,1,-2,-1,2,-1,-2,2,1,2,-1,-2,1,-2,-1}; 12 struct Node 13 { 14 int xx,yy; 15 }; 16 Node Mid,p; 17 queue <Node>q; 18 inline int bfs() 19 { 20 queue <Node>q; 21 int x,y; 22 memset(map,0,sizeof(map)); 23 memset(ans,0,sizeof(ans)); 24 Mid.xx=sx; 25 Mid.yy=sy; 26 map[sx][sy]=1; 27 q.push(Mid); 28 while(!q.empty()) 29 { 30 Mid=q.front(); 31 x=Mid.xx; 32 y=Mid.yy; 33 q.pop(); 34 if(x==ex&&y==ey) break; 35 int x_,y_; 36 for(int i=0; i<8; i++) 37 { 38 x_=x+a[i][0]; 39 y_=y+a[i][1]; 40 if(x_>=0&&y_>=0&&x_<n&&y_<n&&map[x_][y_]==0) 41 { 42 ans[x_][y_]=ans[x][y]+1; 43 p.xx=x_; 44 p.yy=y_; 45 q.push(p); 46 map[x_][y_]=1; 47 } 48 } 49 } 50 } 51 int main() 52 { 53 int cases; 54 scanf("%d",&cases); 55 while(cases--) 56 { 57 scanf("%d",&n); 58 scanf("%d%d%d%d",&sx,&sy,&ex,&ey); 59 bfs(); 60 printf("%d\n",ans[ex][ey]); 61 } 62 return 0; 63 }
小结:第二道bfs。注意队列要开在函数里,不然的话无法保证队列在起始时是空的。