POJ3083 Children of the Candy Corn 搜索

Problem Address:http://poj.org/problem?id=3083


【思路】


学到了广搜的一种新的存储。

假设某个点(i,j),则可以用整数x = (i*w+j)来表示这个点,相当于一个压缩。

而解压为(x/w, x%w)。


这道题题意为求使用左优先和右优先两种策略得到的路径长度以及最短路径长度。

毫无疑问,最短路径使用广搜。

所谓的左优先,是指每次如果左边可以走,则向左继续走下去。如果左边不可走,则再看次左(即此时的后)是否可走。

要注意的是其实这是一种深搜,但又不同于普通的深搜。

这样的搜索是,假如向左走最后无法走出,则需要往回走,而不是从上一处入口继续搜索。而且往回走的时候的正方向是此时而不是彼时的正方向。

这是一种真人的模拟。也可以看做是根本没有所谓的无法走出,因为入口处一定是当前四个方向的最后一个方向,如果其他三个方向都无法走,则原路返回。

当然,用深搜也是可以的。

而至于方向,则可以巧妙低使用dir = (dir+3)%4。也就是把四个方向做成一个循环,然后记录当前方向,再从左边或右边开始。


【代码】


#include <iostream>
using namespace std;

int dd[4][2] = {1,0,0,1,0,-1,-1,0};
int ld[8][2] = {0,-1,-1,0,0,1,1,0,0,-1,-1,0,0,1,1,0};
int rd[8][2] = {0,1,-1,0,0,-1,1,0,0,1,-1,0,0,-1,1,0};

char map[45][45];
char temp[45][45];
int w, h;

int q[1610];
int step[1610];

inline bool check(int i, int j)
{
	if (i<0 || i>=h || j<0 || j>=w) return false;
	else if (temp[i][j]=='#') return false;
	else return true;
}

void init()
{
	int i, j;
	for (i=0; i<h; i++)
	{
		for (j=0; j<w; j++)
		{
			temp[i][j] = map[i][j];
		}
	}
}

void bfs_left_right(int si, int sj, int d[][2], int &ct)
{
	int i;
	ct = 1;
	init();
	int ni, nj;
	int dir = 0;
	ni = si;
	nj = sj;
	while(map[ni][nj]!='E')
	{
		dir = (dir+3)%4;
		for (i=dir; i<dir+4; i++)
		{
			ni += d[i][0];
			nj += d[i][1];
			if (check(ni, nj))
			{
				dir = i;
				ct++;
				break;
			}
			ni -= d[i][0];
			nj -= d[i][1];
		}
	}
	return;
}

void bfs(int si, int sj, int d[][2], int &ct)
{
	int ti, tj, ts;
	int ni, nj;
	int head = 1;
	int tail = 0;
	int i;
	init();
	q[0] = si*40 + sj;
	step[0] = 1;
	temp[si][sj] = '#';
	while(tail<head)
	{
		ti = q[tail]/40;
		tj = q[tail]%40;
		ts = step[tail];
		tail++;
		for (i=0; i<4; i++)
		{
			ni = ti+d[i][0];
			nj = tj+d[i][1];
			if (check(ni, nj))
			{
				q[head] = ni*40 + nj;
				step[head] = ts + 1;
				if (temp[ni][nj]=='E')
				{
					ct = step[head];
					return;
				}
				else 
				{
					temp[ni][nj] = '#';
				}
				head++;
			}
		}
		
	}
}

int main()
{
	int t;
	int i, j;
	int si, sj, flag;
	int lct, rct, ct;
	scanf("%d", &t);
	while(t--)
	{
		scanf("%d %d", &w, &h);
		flag = 0;
		for (i=0; i<h; i++)
		{
			scanf("%s", map[i]);
			if (flag==0)
			{
				for (j=0; j<w; j++)
				{
					if (map[i][j]=='S')
					{
						si = i;
						sj = j;
						break;
					}
				}
			}
		}
		bfs_left_right(si, sj, ld, lct);
		bfs_left_right(si, sj, rd, rct);
		bfs(si, sj, dd, ct);
		printf("%d %d %d\n", lct, rct, ct);
	}
	return 0;
}


你可能感兴趣的:(存储)