POJ 3083 Children of the Candy Corn(走迷宫)

题目链接:POJ 3083

题意:

给一个迷宫,‘#’代表墙,'.'代表可行,’S‘代表入口,’E‘代表出口。分别求出:

①按左、上、右、下顺序前行从入口到出口的步数。

②按右、上、左、下顺序前行从入口到出口的步数。

③从入口到出口的最短步数。

入口在边上但不在拐角处。入口和出口也各算一步。

分析:

最短路径直接用BFS求解。

先分析第一种要求,即左上右下的顺序,第二种与之类似。

入口在不同的边上下一步走的方向下标变化是不一样的。

①当srow=0时,顺序是:   { 0,1 },{ 1,0 },{ 0,-1 },{ -1,0 };【入口在最上面一条边】
②当srow=h-1时,顺序是:{ 0,-1 },{ -1,0 },{ 0,1 },{ 1,0 };【入口在最下面一条边】
③当scol=0时,顺序是:     { -1,0 },{ 0,1},{ 1,0 },{ 0,-1 };【入口在最左面一条边】
④当scol=w-1时,顺序是: { 1,0 },{ 0,-1 }, { -1,0 },{ 0,1}。【入口在最右边一条边】

仔细观察可以发现:①和②其实是同一个序列【相对顺序是一样的】,③和④是同一个序列。所以可以分两类方向逐个查找,沿右上左下顺序前行也是同样的道理。

在方向上还有一点需要考虑。拿测试一来说,移动的顺序是:

(7,1)->(6,1)->(5,1)->(4,1)->(3,1)->(2,1)->(1,1)->(1,2)->(1,3)->......

注意:(1,1)之前的搜索方向顺序是:{ 0,-1 },{ -1,0 },{ 0,1 },{ 1,0 };转向后,

从(1,2)开始搜索方向顺序变为:{ -1,0 },{ 0,1 },{ 1,0 },{ 0,-1 }。通过多写几组下标变化对比可以发现规律:用dfs传递的方向下标是:(当前方向下标+3)%4

难点:

  • 搜索方向的确定
  • dfs传递的参数:下一搜索点,下一次开始搜索方向下标,移动步数,搜索方向数组
  • 找到出口时返回的是step+1
  • 在dfs函数里有两个return:找到出口和return  dfs(...)。

参考链接:POJ 3083

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn = 41;
char s[maxn];
int vis[maxn][maxn],a[maxn][maxn];
int n, w, h, x, y, newx, newy, t;
int srow, scol, erow, ecol, startindex;
//srow,scol,erow,ecol分别是起点终点下标,startindex是开始探索方向下标
int ansbfs, ansleft, ansright;
int flag = 0;

int dirleft1[4][2] = { { 0,1 },{ 1,0 },{ 0,-1 },{ -1,0 } };
int dirleft2[4][2] = { { -1,0 },{ 0,1},{ 1,0 },{ 0,-1 } };
int dirright1[4][2] = { { 0,-1 },{ 1,0 },{ 0,1 },{ -1,0 } };
int dirright2[4][2] = { { 1,0 },{ 0,1 },{ -1,0 },{ 0,-1 } };
int dfs(int x, int y, int k, int step, int dir[4][2])
{
	for (int i = 0;i < 4;i++)
	{
		t = (k + i) % 4;//这样避免了方向下标越界
		newx = x + dir[t][0];
		newy = y + dir[t][1];
		if (newx == erow&&newy == ecol) return step+1;//+1是因为终点也算一个
		if(newx < 0 || newy < 0 || newx >= h || newy >= w || a[newx][newy]||(newx==srow&&newy==scol)) continue;
		//下标不能越界;遇墙跳过;不能再去起点
		return dfs(newx, newy, (t+3)%4, step + 1, dir);
		//因为下一次再从左/右边开始时可能已经‘转向’了,例如测试一里从(1,1)到(1,2),所以这里要传递(t+3)%4,而不是k
	}
}

int dirbfs[4][2] = { {1,0},{-1,0},{0,1},{0,-1} };
struct Node {
	int a;
	int b;
	int step;
}cur,nextnode;
int bfs()
{
	queue<Node> q;
	cur.a = srow;
	cur.b = scol;
	cur.step = 1;
	vis[cur.a][cur.b] = 1;
	q.push(cur);
	while (!q.empty())
	{
		cur = q.front();
		q.pop();
		for (int i = 0;i < 4;i++)
		{
			x = cur.a + dirbfs[i][0];
			y = cur.b + dirbfs[i][1];
			if (x < 0 || y < 0 || x >= h || y >= w || vis[x][y] || a[x][y]) continue;
			nextnode.a = x;
			nextnode.b = y;
			nextnode.step = cur.step + 1;
			vis[x][y] = 1;
			if (x == erow&&y == ecol) return cur.step+1;
			q.push(nextnode);
		}
	}
}

int main()
{
#ifdef LOCAL
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	cin >> n;
	while (n--)
	{
		cin >> w >> h;
		for (int i = 0;i < h;i++)
		{
			cin >> s;
			for (int j = 0;j < w;j++)
			{
				if (s[j] == '#') a[i][j] = 1;//a[i][j]=1代表墙
				else if (s[j] == '.') a[i][j] = 0;
				else if (s[j] == 'S')
				{
					a[i][j] = 0;
					srow = i;
					scol = j;
				}
				else if (s[j] == 'E')
				{
					a[i][j] = 0;
					erow = i;
					ecol = j;
				}
			}
		}
		ansbfs = ansleft = ansright = 0;
		if (srow == 0 || srow == h - 1)
		{
			if (srow == 0) startindex = 0;
			else startindex = 2;
			ansleft = dfs(srow, scol, startindex, 1, dirleft1);
			ansright = dfs(srow, scol, startindex, 1, dirright1);
		}
		else if(scol==0||scol==w-1)
		{
			if (scol == 0) startindex = 0;
			else startindex = 2;
			ansleft = dfs(srow, scol, startindex, 1, dirleft2);
			ansright = dfs(srow, scol, startindex, 1, dirright2);
		}
		memset(vis, 0, sizeof(vis));
		ansbfs = bfs();
		cout << ansleft<<" "<<ansright<<" "<<ansbfs << endl;
	}
	return 0;
}




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值