面试笔试算法:广搜

用于计算地图中起点到终点最短步长问题。

广搜时,偶尔会有疑惑,为什么可以在标记地图上直接标上步数?会不会有别的点广搜时步数更小的情况?答案当然是不会的,在初始情况时,一定要把所有初始点塞进队列中,才能开始广搜,这样保证每一轮都稳定地往起始点外扩一个步长,并且先标记到的格子中记录的一定是最短步长。

​ 难得的休息日,小明起床时就已经 11 点多了,他常去的馅饼店一般 12 点就没饭了,他需要赶紧洗漱,出门,然后去馅饼店吃饭,到了小区大门口他傻眼了,前几天贴的修路公告成为了现实,现在小区门外已经成为工地,到处都是路障。小区门口到馅饼店的路形如一个 n×m 的二维矩阵,能走的道路被标记成了 .,路障被标记成了 #,小区大门被标记成了 2,馅饼店被标记成了 3,小明可以在矩阵上上下左右移动,每移动一次代表走了一步,现求小明从小区门口最少走多少步才能到达馅饼店,若无法到达则输出 −1。

#include <iostream>
#include <queue>
using namespace std;

struct node {
	int x, y, step;//每一点记录步数
};

int sx, sy;
char mmap[505][505];
int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};

int main(){
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; i ++){
		for (int j = 1; j <= m; j++){
			cin >> mmap[i][j];
			if (mmap[i][j] == '2'){
				sx = i;
				sy = j;
			}
		}
	}
	queue<node> que;
	que.push((node){sx, sy, 0});
	while(!que.empty()){
		node temp = que.front();//取出可用节点扩展
		que.pop();
		for (int i = 0; i < 4; i++){
			int x = temp.x + dir[i][0];
			int y = temp.y + dir[i][1];
			if (mmap[x][y] == '3'){
				cout << temp.step + 1 << endl;
				return 0;
			}
			if (mmap[x][y] == '.'){//可用的子节点
				mmap[x][y] = 0;//直接改原数组
				que.push((node){x, y, temp.step + 1});//将可用节点压入队列
			}
		}
	}
	cout << -1 << endl;
	return 0;
}

农民约翰有很多牛,他想交易其中一头被Don称为骑士的牛。这头牛有一个独一无二的超能力,在农场里像骑士一样地跳(就是我们熟悉的象棋中马的走法)。虽然这头神奇的牛不能跳到树上和石头上,但是它可以在牧场上随意跳,我们把牧场用一个 x,y

的坐标图来表示。

​ 这头神奇的牛像其它牛一样喜欢吃草,给你一张地图,上面标注了骑士的开始位置,树、灌木、石头以及其它障碍的位置,除此之外还有一捆草。现在你的任务是,确定骑士要想吃到草,至少需要跳多少次。骑士的位置用 K​
来标记,障碍的位置用 ∗​ 来标记,草的位置用 H​

来标记。

#include <iostream>
#include <queue>
using namespace std;

int dir[8][2] = {1, 2, 1, -2, -1, 2, -1, -2, 2, 1, 2, -1, -2, 1, -2, -1};
//int sx, sy;
int n, m;
char mmap[200][200];

struct node {
	int x, y, step;
};

int main(){
	cin >> m >> n;
	queue<node> que;
	for (int i = 5; i < n + 5; i++){
		for (int j = 5; j < m + 5; j++){
			cin >> mmap[i][j];
			if (mmap[i][j] == 'K'){
				//sx = i;
				//sy = j;
				que.push((node){i, j, 0});
			}
		}
	}
	while(!que.empty()){
		node t = que.front();
		que.pop();//!!!关键
		for (int i = 0; i < 8; i++){
			int x = t.x + dir[i][0];
			int y = t.y + dir[i][1];
			if (mmap[x][y] == 'H'){
				cout << t.step + 1 << endl;
				return 0;
			}
			if (mmap[x][y] == '.'){
				que.push((node){x, y, t.step + 1});
				mmap[x][y] = '#';//!!!注意关键
			}
		}
	}
	cout << -1 << endl;
	return 0;

}

有一个 n 行 m 列的棋盘( 1<n,m≤400 ),在某个点上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。

#include <iostream>
#include <queue>
using namespace std;

int dir[8][2] = {1, 2, 1, -2, -1, 2, -1, -2, 2, 1, 2, -1, -2, 1, -2, -1};
int sx, sy;
int n, m;
int mmap[500][500];

struct node {
	int x, y, step;
};

int main(){
	cin >> n >> m >> sx >> sy;
	queue<node> que;
	que.push((node){sx, sy, 0});
	mmap[sx][sy] = -1;
	while(!que.empty()){
		node t = que.front();
		que.pop();//!!!关键
		for (int i = 0; i < 8; i++){
			int x = t.x + dir[i][0];
			int y = t.y + dir[i][1];
			if (x >= 1 && x <= n && y >= 1 && y <= m && mmap[x][y] == 0){
				mmap[x][y] = t.step + 1;
				que.push((node){x, y, t.step + 1});
			}
		}
	}
	for (int i = 1; i <= n; i++){
		for (int j = 1; j <= m; j++){
			j != 1 && (printf(" "));
			if (mmap[i][j] == -1) {
				cout << 0;
			}else if (mmap[i][j] == 0){
				cout << -1;
			}else{
				cout << mmap[i][j];
			}
		}
		cout << endl;
	}
	
	return 0;

}

年轻的拉尔夫开玩笑地从一个小镇上偷走一辆车,但他没想到的是那车属于警察局。并且车上装有用于发射车子移动路线的装置。那个装置太旧了,以至于只能发射关于那辆车的移动路线的方向信息。

​ 通过使用一张小镇的地图,帮助警察局找到那车。表示出该车最终所有可能的位置。

​ 小镇的地图是矩形的,上面的符号用来标明那儿可以行车和那儿不行。“.”
表示小镇上那块地方是可以行车的,符号 “X” 表示此处不能行车。拉尔夫所开小车的初始位置,用字符的 “∗”

,表示,且汽车能从初始位置通过。汽车能向四个方向移动:向北(上),南(下),西(左),东(右);拉尔夫所开小车的行动路线是通过一组给定的方向来描述的,在每个给定的方向,拉尔夫驾驶小车通过小镇上的一个或更多的可行车地点。

#include <iostream>
#include <queue>
#include <string>

using namespace std;

int dir[4][2]={0, 1, 1, 0, 0, -1, -1, 0};
char mmap[100][100];

struct node{
	int x, y, step;
};

int main(){
	int n, m;
	queue<node> que;
	cin >> n >> m;
	for (int i = 1; i <= n; i++){
		for (int j = 1; j <= m; j++){
			//scanf(" %c", &mmap[i][j]);
			cin >> mmap[i][j];
			if (mmap[i][j] == '*'){
				mmap[i][j] = '.';
				que.push((node){i, j, 0});
			}
		}
	}
	int k, r;
	//string dirc;
	cin >> k;//方向数
	for (int i = 0; i < k; i++){
		string dirc;
		cin >> dirc;//!!!!注意方向反的
		int check[55][55] = {0}, qsize = que.size();
		if (dirc == "NORTH"){
			r = 3;
		}else if(dirc == "SOUTH"){
			r = 1;
		}else if(dirc == "EAST"){
			r = 0;
		}else if(dirc == "WEST"){
			r = 2;
		}
		
		while(que.front().step == i){//队列中上一个方向的点
		//while(qsize--){//队列中上一个方向的点
			node pre = que.front();
			que.pop();
			int x = pre.x;
			int y = pre.y;

			while(mmap[x+ dir[r][0]][y + dir[r][1]] == '.'){
				x = x + dir[r][0];
				y = y + dir[r][1];
				if (check[x][y] == 0) {que.push((node){x, y, i + 1}); check[x][y] =1;}//一定要加check!!!不然通不过一些用例
			}
		}
	}
	
	while(!que.empty()){
		node t = que.front();
		que.pop();
		mmap[t.x][t.y] = '*';
	}
	//输出地图
	for (int i = 1; i <= n; i++){
		for (int j = 1; j <= m; j++){
			cout << mmap[i][j];
		}
		cout << endl;
	}
	
	return 0;
	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值