【广搜\状态压缩】拯救Angel行动

拯救Angel行动

(angel.pas/in/out)

Problem

一切危险都结束了。JLHS人在Angel的带领下来到了新的新的大陆,并且来到了一个奇怪的地方(今江苏南京)。这里的土著人对他们似乎不是很友好(中国以前也有土著?!),在短暂的交涉以后,他们把带头大哥Angel抓了起来,并且放到了一个迷宫当中。

土著人比JLHS岛上的奇怪生物明智多了,他们把Angel关在了一个N*M(M, N<=15)的迷宫中(制作成本高了,迷宫就小了……),迷宫里有不可逾越的墙和P种门(p<=10)。从一个格子移动到另一个的时间是1,拿所在格子的钥匙的时间以及用钥匙开门的时间不计。你的任务是用最少的时间救出Angel(粗心的mld忘记说了:救援队一开始在1,1点,Angel在n,m点)

Input

第1行3个整数,表示N,M,P的值。 第2行1个整数K,表示迷宫中门的墙的总个数。 以后K行,每行5个数,分别为X1,Y1,X2,Y2和G。 G>0时,代表(X1,Y1)->(X2,Y2)有一个G类的门。 G=0时,代表(X1,Y1)->(X2,Y2)有一个墙,其中|X1-X2|+|Y1-Y2|=1。 然后是一个整数S,代表了钥匙的个数 然后S行,每行3个数,X,Y,Q,代表(X,Y)位置有一个开启Q门的钥匙。

Output

输出包含一个整数,代表救出Angel的最少时间,若不能救出,则输出“Poor Angel!”

Sample Input

4 4 9

9

1 2 1 3 2

1 2 2 2 0

2 1 2 2 0

2 1 3 1 0

2 3 3 3 0

2 4 3 4 1

3 2 3 3 0

3 3 4 3 0

4 3 4 4 0

2

2 1 2

4 2 1

Sample Output

14



这道题测试数据有点问题,但是应该程序没有问题。


第一次测手残了很多地方,但是还是有很多分。。

1、没有注意到一个格子可能放有多个钥匙。

2、循环队列,队列空的判断只能是l!=r,而不能是l

3、广搜的判重必须增加一维存的钥匙的状态,因为可能捡到钥匙会往回走。

4、判断到达终点应该在入队的地方,而不是在出队的地方,因为那样会浪费很多时间。


除此之外,就没有难点了


#include 
#include 
#include 

struct node
{
	long x;
	long y;
	long s;
	long k;
};
node que[2000010];
long qmod = 2000000;
long wall[20][20][20][20];
long map[20][20];
bool hash[20][20][3000];
long n, m, p;
const long dx[] = {-1,1,0,0};
const long dy[] = {0,0,-1,1};

long getint()
{
	long rs=0;bool sgn=1;char tmp;
	do tmp = getchar();
	while (!isdigit(tmp)&&tmp-'-');
	if (tmp == '-'){tmp=getchar();sgn=0;}
	do rs=(rs<<3)+(rs<<1)+tmp-'0';
	while (isdigit(tmp=getchar()));
	return sgn?rs:-rs;	
}

void bfs()
{
	long l = 0;
	long r = 0;
	node u; node v;
	r ++;
	que[r].x = 1;
	que[r].y = 1;
	que[r].s = 0;
	que[r].k = 0;
	hash[1][1][0] = true;
	while (l != r)
	{
		l ++;
		if (l == qmod)
			l = 0;
		u = que[l];

		for (long i=0;i<4;i++)
		{
			v.x = u.x + dx[i];
			v.y = u.y + dy[i];
			v.s = u.s;
			v.k = u.k;
			long wll = wall[u.x][u.y][v.x][v.y];
			if (map[v.x][v.y]>-1 && wll>-1 && (wll==0 || (u.k&(1<0)
					v.k |= map[v.x][v.y];
				if (hash[v.x][v.y][v.k]) continue;

				v.s ++;
				r ++;
				if (r == qmod)
					r = 0;
				que[r] = v;

				if (v.x == n && v.y == m)
				{
					printf("%ld",v.s);
					return;
				}
			}
		}
	}
	printf("Poor Angel!");
}

int main()
{
	freopen("angel.in","r",stdin);
	freopen("angel.out","w",stdout);

	n = getint();
	m = getint();
	p = getint();
	for (long i=0;i


你可能感兴趣的:(NOIP)