P1443 马的遍历

10 篇文章 0 订阅
8 篇文章 0 订阅

题目连接:https://www.luogu.com.cn/problem/P1443


这道题问的是最少要几步,所以可以用 b f s bfs bfs广度优先搜索)解决。


初始化

b f s bfs bfs 要用到队列。

队列有两种表示方法:

  1. 数组 q [ i ] q[i] q[i] 表示队列的第 i i i 项.

    headtail指向队头和队尾。

  2. queue:先进先出的线性表。

    需要头文件 #include<queue>

    定义 queue <int> q;

    入队 q.push(x);

    出队 q.pop();

    查询队列中元素个数 q.size()

代码:

for (int i = 1;i <= n;i ++)
	for (int j = 1;j <= m;j ++)
		map[i][j] = -1; //初始化,答案可能为0 
map[x][y] = 0; //马的初始坐标答案为0 
head = tail = 1; //队首和队尾初始化 
q[head][1] = x; //队首的坐标进队 
q[head][2] = y;


增量数组

题目中,马走的是日字形

如图所示,增量数组为

d x [ ] = { 1 , 2 , 2 , 1 , − 1 , − 2 , − 2 , − 1 } dx[ ] = \{1, 2, 2, 1, -1, -2, -2, -1\} dx[]={1,2,2,1,1,2,2,1}

d y [ ] = { 2 , 1 , − 1 , − 2 , − 2 , − 1 , 1 , 2 } dy[ ] = \{2,1,-1,-2,-2,-1,1,2\} dy[]={2,1,1,2,2,1,1,2}


bfs

while (head <= tail)//如果队列里有数 
{
	for (int i = 0;i < 8;i ++)
	{
		int newx = q[head][1] + dx[i]; 
		int newy = q[head][2] + dy[i];
		if (newx > n || newx < 1 || newy > m || newy < 1) continue;
		//判断是否出界 
		if (map[newx][newy] >= 0) continue;
		//有没有访问过 
		q[++tail][1] = newx;
		q[tail][2] = newy;
		//进队 
		map[newx][newy] = map[q[head][1]][q[head][2]] + 1;
		//标记答案 
	}
	head ++;//队头出队 
}

输出

题目中要求 左对齐,宽五格,在c++里的实现方法为printf("%-5d",map[i][j]);

完整代码

#include<iostream>
#include<iomanip>
#include<cstdio>
using namespace std;

int n,m,x,y;//n,m表示棋盘的长和宽,x,y表示马的坐标 
int map[450][450];//用于存图 
int head,tail;//队首和队尾 
int q[160050][5];//队列 q[i][1]表示i的x坐标
                 //q[i][2]表示y坐标
int dx[] = {2,2,1,1,-2,-2,-1,-1};//增量数组 
int dy[] = {1,-1,2,-2,1,-1,2,-2};

int main()
{
	cin >> n >> m >> x >> y;
	for (int i = 1;i <= n;i ++)
		for (int j = 1;j <= m;j ++)
			map[i][j] = -1;//初始化,答案可能为0 
	map[x][y] = 0;//马的初始坐标答案为0 
	head = tail = 1;//队首和队尾初始化 
	q[head][1] = x;//队首的坐标进队 
	q[head][2] = y;
	while (head <= tail)//如果队列里有数 
	{
		for (int i = 0;i < 8;i ++)
		{
			int newx = q[head][1] + dx[i]; 
			int newy = q[head][2] + dy[i];
			if (newx > n || newx < 1 || newy > m || newy < 1) continue;
			//判断是否出界 
			if (map[newx][newy] >= 0) continue;
			//有没有访问过 
			q[++tail][1] = newx;
			q[tail][2] = newy;
			//进队 
			map[newx][newy] = map[q[head][1]][q[head][2]] + 1;
			//标记答案 
		}
		head ++;//队头出队 
	}
	for (int i = 1;i <= n;i ++)
	{
		for (int j = 1;j <= m;j ++)
			printf("%-5d",map[i][j]);//输出 
		cout << endl;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值