NOJ 木乃伊迷宫代码和思路

这道题是分支限界的方法,工具是BFS(广度优先遍历),下面列举了我觉得有问题的几个点(如果有补充或者还有其他问题,请私信,或者评论):
1.墙的问题:这道题每个格子只有右边和下边有墙,但是注意一点,如果一个格子的左边的格子有了墙,那么这个格子也就相当于左边有了墙,所以在读入墙的时候,我们要注意一点:一个格子的左边有墙,那么它右边的格子的左边也就要加上一堵墙,但是这个加墙的前提是右边有墙的格子不是最右边的格子,加在格子下面的墙是同理的

2.这里的走步数的话,设置一个二维数组来保存人走的方向,木乃伊的话一定要在列上走到人所在的那一列,如果碰到墙的话,就一直在那个格子不动!!!走到人的那一列之后才开始在x方向或者说列方向上运动。这里木乃伊追赶的是人在走一步之后的位置。

3.这里要记得设置个visit数组,这样来判重,防止一样的情况多次出现,从而人没有办法走到出口,而一直在迷宫中转圈圈

4.可以写个函数来判断现在这个方向是不是可以走,传过去的形参是当前结点和我们选择的方向,然后在函数中设置一个next结点,通过next结点来保存下一个进入队列的结点的状态,并通过next中的bool类型的变量来保存这个结点是否可以进入队列。如果函数返回结点中这个bool型变量的值是false(有三种情况会false:一是人或者木乃伊越界了——超过了迷宫的边界;二是人被木乃伊追到了——木乃伊追到人是指在人已经动了之后在追的,而不是追先前的人的状态或者说不是我们传过来的那个结点所在的位置;三是遇到了墙,人在这个方向走不通),说明不能进入队列。
代码如下:

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;

struct Node {
	int now_xr, now_yr;
	int now_xm, now_ym;
	bool useful;
};

int visit[6][6][6][6];//保存状态
int a[6][6][4];//对应每个方格是否有墙,以及墙在哪个方向
//0代表右方,1代表左方,2代表下方,3代表上方 
int wish_x, wish_y;
int d[4][2] = { {0,1}/*向右走*/,{0,-1}/*向左走*/,{1,0}/*向下走*/,{-1,0}/*向上走*/ };

queue<Node> map_1;

void input() {//读入
	int n;
	cin >> n;
	int x, y, dir;
	for (int i = 0; i < n; i++) {
		if (dir == 0) {
			a[x][y][2] = 1;
			if (x < 5) {//没有比最右边的格子更加右边的格子
				a[x ][y][3] = 1;
			}
		}
		else {
			a[x][y][0] = 1;
			if(y<5){//x==5 已经是最下面了
				a[x][y][1] = 1;
			}
		}
	}
	Node now;
	cin >> now.now_xm >> now.now_ym >> now.now_xr >> now.now_yr;
	cin >> wish_x >> wish_y;
	map_1.push(now);
}

bool iswall(int x, int y, int i) {//判断是不是撞到墙
	switch (i) {
	case 0://向右走
		return a[x][y][0];

	case 1://向左走
		return a[x][y][1];

	case 2://向下走
		return a[x][y][2];

	case 3://向上走
		return a[x][y][3];
	}
	return -1;//代表传过来的i值错误
}

Node decide(Node now, int i) {
	//判断是否撞到了墙以及是否越界
	Node next;
	next.now_xr = now.now_xr + d[i][0], next.now_yr = now.now_yr + d[i][1];
	if ((next.now_xr < 0 || next.now_xr >= 6 || next.now_yr < 0 || next.now_yr >= 6) || iswall(now.now_xr, now.now_yr, i)) {
		next.useful = false;
		return next;
	}
	next.now_xm = now.now_xm;
	next.now_ym = now.now_ym;
	int res = 2;
	//先到同一列 
	while (res--) {
		if (next.now_ym < next.now_yr && !iswall(next.now_xm, next.now_ym, 0)) {
			next.now_ym++;
		}
		else if (next.now_ym > next.now_yr && !iswall(next.now_xm, next.now_ym, 1)) {
			next.now_ym--;
		}
		else if (next.now_ym == next.now_yr) {
			if (next.now_xm < next.now_xr && !iswall(next.now_xm, next.now_ym, 2)) {
				next.now_xm++;
			}
			else if (next.now_xm > next.now_xr && !iswall(next.now_xm, next.now_ym, 3)) {
				next.now_xm--;
			}
			if (next.now_xm == next.now_xr && next.now_ym == next.now_yr) {
				next.useful = false;
				return next;
			}
		}
	}
	/*if (visit[next.now_xr][next.now_yr][next.now_xm][next.now_ym]) {
		next.useful = false;//前面访问过的点不再入队
	}
	else {
		visit[next.now_xr][next.now_yr][next.now_xm][next.now_ym] = 1;
		next.useful = true;
	}
	return next;*/
	next.useful = true;
	return next;
}

bool bfs() {
	Node now;
	while (!map_1.empty()) {
		now = map_1.front();
		map_1.pop();

		if (visit[now.now_xr][now.now_yr][now.now_xm][now.now_ym]) {
			continue;
		}
		visit[now.now_xr][now.now_yr][now.now_xm][now.now_ym] = 1;
		Node next;
		for (int i = 0; i < 4; i++) {
			next = decide(now, i);
			if (next.useful) {
				if (next.now_xr == wish_x && next.now_yr == wish_y) {//到了出口的地方
					return true;
				}
				else map_1.push(next);//没有走到人的位置,入队,同时也说明了木乃伊没有走到人的位置 
			}
		}
	}
	return false;
}

int main() {
	
	input();

	if (bfs())
	{
		cout << "Yes" << endl;
	}
	else
	{
		cout << "No" << endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小编程员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值