题目
有一个n×m的棋盘,在某个点(x,y)上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。
输入输出格式
输入格式
输入只有一行四个整数,分别为n,m,x,y。
输出格式
一个n×m的矩阵,代表马到达某个点最少要走几步(不能到达则输出−1)。
输入输出样例
输入样例
3 3 1 1
输出样例
0 3 2
3 -1 1
2 1 4
解析
这道题目使用的是广度优先搜索,会优先考虑每种状态和初始状态的距离,形象点说,与初始状态越接近的情况就会越先考虑。再具体一点:每个时刻(阶段)要做的事情就是从上个时刻(阶段)每个状态扩展出新的状态。
广度优先搜索使用队列实现:先将初始状态加入到空的队列中,然后每次去除队首,找出队首所能转移到的状态,再将其压入队列;如此反复,直到对列为空。这样就能保证一个状态在被访问的时候一定是采用的最短路径。
广度优先搜索的一般形式如下:
Q.push(初始状态);//将初始状态入队
while(!Q.empty()){
Statue u = Q.front();//取出队首
Q.pop();//出队
for(枚举所有可扩展状态){
if(是合法的){
Q.push(v);//入队
}
}
}
对于此问题,先建立一个结构体数组用于存储扩展的结点。先让起点入队,然后在队列取状态逐个扩展。代码如下:
#include<bits/stdc++.h>
using namespace std;
int n,m,x,y,dis[401][401];
int walk[8][2]={{-2,1},{2,1},{-2,-1},{2,-1},{-1,2},{1,2},{-1,-2},{1,-2}};
struct node{
int x,y;
};
bool pd(int x,int y){
if(x<1||x>n||y<1||y>m||dis[x][y]!=-1){
return false;
}
return true;
}
void bfs(){
node now,next;
queue<node>q;
now.x=x;
now.y=y;
q.push(now);
dis[now.x][now.y]=0;
while(!q.empty()){
node t=q.front();
q.pop();
for(int i=0;i<8;i++){
int tx=t.x+walk[i][0];
int ty=t.y+walk[i][1];
if(pd(tx,ty)){
next.x=tx;
next.y=ty;
q.push(next);
dis[next.x][next.y]=dis[t.x][t.y]+1;
}
}
}
}
int main(){
scanf("%d%d%d%d",&n,&m,&x,&y);
memset(dis,-1,sizeof(dis));
bfs();
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
printf("%d ",dis[i][j]);
}
printf("\n");
}
return 0;
}