【广搜\状态压缩】拯救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<r。

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

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


除此之外,就没有难点了


#include <cstdio>
#include <string>
#include <cstring>

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<<wll)) ))
			{
				if (map[v.x][v.y]>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<m+2;i++)
		map[0][i] = map[n+1][i] = -1;
	for (long i=0;i<n+2;i++)
		map[i][0] = map[i][m+1] = -1;
	long k = getint();
	for (long i=1;i<k+1;i++)
	{
		long x1,y1,x2,y2;
		x1 = getint();
		y1 = getint();
		x2 = getint();
		y2 = getint();
		long G = getint();
		if (G == 0)
			wall[x1][y1][x2][y2] =
			wall[x2][y2][x1][y1] = -1;
		else
			wall[x1][y1][x2][y2] =
			wall[x2][y2][x1][y1] = G;
	}
	long s = getint();
	for (long i=1;i<s+1;i++)
	{
		long x,y,q;
		x = getint();
		y = getint();
		q = getint();
		map[x][y] |= (1<<q);
	}

	bfs();
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Matlab中,angle函数可以用atan2(imag(h), real(h))来表示。这个函数用于计算给定复数的幅角。具体实现时,可以将待计算的复数h分别作为虚部和实部输入到atan2函数中。 此外,Matlab中还提供了ifft2函数,用于进行二维离散傅里叶反转变换。ifft2(X)表示对矩阵X进行傅里叶反转变换,返回与X大小相同的矩阵Y。如果需要指定变换后的矩阵大小为m&times;n,可以使用ifft2(X,m,n)函数,并用0进行补全。例如: ``` I = imread('E:\persional\matlab\images\paopao.tif'); K = fft2(I); % 进行傅里叶变换 L = fftshift(K); % 平移 M = ifft2(K); % 傅里叶反转函数 figure, subplot(121), imshow(uint8(abs(L)/256)); % 显示频谱图 subplot(122), imshow(uint8(M)); % 反转后得到的图像 ``` 上面的代码展示了对图像进行傅里叶变换、平移和傅里叶反转的过程,并绘制了频谱图和反转后的图像。 另外,Matlab还提供了fft2函数用于进行二维离散傅里叶变换。例如: ``` I = imread('E:\persional\matlab\images\lena.bmp'); I = imread('E:\persional\matlab\images\house.tif'); I = im2double(I); J = fft2(I); % 傅里叶变换 K = abs(J/256); figure, subplot(131), imshow(I); subplot(132), imshow(J); subplot(133), imshow(K); % 频谱图 ``` 上述代码展示了对图像进行二维离散傅里叶变换,并绘制了原始图像、傅里叶变换后的图像和频谱图。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Matlab中angle函数内容详解](https://blog.csdn.net/cao_jie_xin/article/details/91128887)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [图像Radon变换与傅里叶变换(matlab)](https://blog.csdn.net/weixin_56260304/article/details/127628704)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值