题目描述
有一个n*m的棋盘(1<n,m<=400),在某个点上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步
输入
一行四个数据,棋盘的大小n m和马的坐标x y
3 3 1 1
输出
一个n*m的矩阵,代表马到达某个点最少要走几步(不能到达则输出-1)
输出格式 数字左对齐,宽五格。
0 3 2
3 -1 1
2 1 4
思路
使用广度优先搜索(BFS),因为马走日,所以一个点可以走八个点
用一个数组来记录每个点的最少到达步数,初始全部赋值为-1;
一个新的点的步数,是用弹出的队首元素的步数加一 : mp[newX][newY]=mp[top.x][top.y]+1;
输出格式:数字左对齐,宽五格。printf(" %-5d ",mp[i][j]);
%-5d :“-”表示左对齐,不带“-”号表示右对齐。数字“5”表示输出宽度为5位,“d”表示输出类型为整型。
代码
#include<iostream>
#include<queue>
using namespace std;
struct node{
int x,y;
}S,Node; //S 为起点 , Node 为临时结点
int n,m,p1,p2;
int mp[400][400]; // 用来存放步数
bool inq[101][101]= {false}; // 记录(x,y)是否已入过队
int X[8] = {1,2,-1,-2,-2,-1,1,2}; // 增量数组 因为马走日,所以一个点可以走八个地方
int Y[8] = {2,1,2,1,-1,-2,-2,-1};
bool test(int x,int y) //检测(x,y)是否有效
{
if(x>=n || x<0 || y>=m || y<0) return false; //超过边界
if(inq[x][y] == true) return false; //已经入过队
return true;
}
void bfs()
{
queue<node> q; // 定义队列
q.push(S);
while(!q.empty())
{
node top = q.front(); //取出队首元素
q.pop(); // 队首元素出列
for(int i=0;i<8;i++) //循环8次,得到8个相邻位置
{
int newX = top.x + X[i];
int newY = top.y + Y[i];
if(test(newX,newY)) //测试位置有效
{
mp[newX][newY]=mp[top.x][top.y]+1; //从它的上一个结点的步数加一
Node.x = newX,Node.y = newY;
q.push(Node); //结点Node 入队
inq[newX][newY] = true; //表示已入队,标记
}
}
}
}
int main()
{
for(int i=0;i<400;i++) //直接粗暴的为初始数组赋值
{
for(int j=0;j<400;j++)
{
mp[i][j]=-1; //都是-1,可以最后直接得到哪个位置没到过
}
}
cin>>n>>m>>p1>>p2;
S.x = p1-1;
S.y = p2-1;
mp[p1-1][p2-1]=0; //起点的步数为0
inq[p1-1][p2-1] = true; // 起点入队
bfs();
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
printf("%-5d",mp[i][j]); //输出数字左对齐,宽5格
}
if(i+1!=n) cout<<endl;
}
return 0;
}