USACO 玉米田迷宫 Corn Maze

本文介绍了USACO题目Corn Maze的解决方案,通过BFS算法来处理包含传送门的迷宫问题。关键在于处理传送门不耗费时间的特性,避免无限循环,使用checked数组记录已访问点和传送门状态。

移步到新Blog查看图片 (此Blog已废弃,图片已失效)




这题是一个大坑。

首先我们想到了BFS,这个题就是一个简单到不能再简单的Maze加上传送门就是了。

但是有一点是传送门不费时啊!!什么鬼。所以我们要先判传送门

为什么呢?我记得有一组测试数据包括了这种情况


这不清真

另外,好像还有一个点是全都是传送门的情况。


判传送门(并不是判队首元素位于传送门,而是队首坐标移动之后),传送过去之后耗时不加,队列保存传送后的位置,这样就不会产生无限传送死循环的问题。

但是关于情况2怎么办?我们利用BFS的性质,把传送门(传过去之后)打上标记,然后就不用他了。(每一次用都是最早用他)

传送门I hate you


读入的时候记录传送门的相对坐标,像这样:

scanf("%s",&mapx[i]);
		for (int j=0;j<m;j++)
		{
			if (mapx[i][j]=='=')
			{
				ex=i;ey=j;
			}
			else if (mapx[i][j]=='@')
			{
				sx=i;sy=j;
			}
			else if (mapx[i][j]>='A' && mapx[i][j]<='Z')
			{
				if (toit[mapx[i][j]-65][0][0]==-1)
				{
					toit[mapx[i][j]-65][0][0]=i; toit[mapx[i][j]-65][0][1]=j;
				}
				else toit[mapx[i][j]-65][1][0]=i; toit[mapx[i][j]-65][1][1]=j;
			}
		}
之后碰到传送门直接查表。,顺便记下起点sxsy和重点exey

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;

queue<int>quex,quey;
int cachex,cachey;
char mapx[400][400]={0};
int sx,sy,ex,ey,n,m;
int head=0,tail=1;
int timex[100000]={0},toit[50][2][2];
bool checked[400][400]={false};
int wayx[4]={-1,0,1,0},wayy[4]={0,1,0,-1};

int main()
{
	memset(toit,-1,sizeof(toit));
	scanf("%d%d",&n,&m);
	for (int i=0;i<n;i++)
	{
		scanf("%s",&mapx[i]);
		for (int j=0;j<m;j++)
		{
			if (mapx[i][j]=='=') { ex=i;ey=j;}
			else if (mapx[i][j]=='@') { sx=i;sy=j;}
			else if (mapx[i][j]>='A' && mapx[i][j]<='Z')
			{
				if (toit[mapx[i][j]-65][0][0]==-1) toit[mapx[i][j]-65][0][0]=i; toit[mapx[i][j]-65][0][1]=j;
				else toit[mapx[i][j]-65][1][0]=i; toit[mapx[i][j]-65][1][1]=j;
			}
		}
	}

	quex.push(sx); quey.push(sy);
	timex[1]=0;
	while (quex.size()>0)
	{
		head++;
		cachex=quex.front(); cachey=quey.front();
		if (mapx[cachex][cachey]=='=')
		{
			printf("%d\n",timex[head]);
			return 0;
		}
		for (int i=0;i<=3;i++)
			if (cachex+wayx[i]>=0 && cachex+wayx[i]<n && cachey+wayy[i]>=0 && cachey+wayy[i]<m)
			{
				if (mapx[cachex+wayx[i]][cachey+wayy[i]]>='A' && mapx[cachex+wayx[i]][cachey+wayy[i]]<='Z' && checked[cachex+wayx[i]][cachey+wayy[i]]==false)
				{
					if (cachex+wayx[i]==toit[mapx[cachex+wayx[i]][cachey+wayy[i]]-65][0][0] && cachey+wayy[i]==toit[mapx[cachex+wayx[i]][cachey+wayy[i]]-65][0][1])
					{
						tail++;
						quex.push(toit[mapx[cachex+wayx[i]][cachey+wayy[i]]-65][1][0]); quey.push(toit[mapx[cachex+wayx[i]][cachey+wayy[i]]-65][1][1]);
						timex[tail]=timex[head]+1;
						checked[cachex+wayx[i]][cachey+wayy[i]]=true;
						//cout<<"A  "<<"X= "<<toit[mapx[cachex+wayx[i]][cachey+wayy[i]]-65][1][0]<<" Y= "<<toit[mapx[cachex+wayx[i]][cachey+wayy[i]]-65][1][1]<<" Timex= "<<timex[tail]<<" X= "<<cachex<<" Y= "<<cachey<<endl;
					}
					else 
					{
						tail++;
						quex.push(toit[mapx[cachex+wayx[i]][cachey+wayy[i]]-65][0][0]); quey.push(toit[mapx[cachex+wayx[i]][cachey+wayy[i]]-65][0][1]);
						timex[tail]=timex[head]+1;
						checked[cachex+wayx[i]][cachey+wayy[i]]=true;
						//cout<<"B  "<<"X= "<<toit[mapx[cachex+wayx[i]][cachey+wayy[i]]-65][0][0]<<" Y= "<<toit[mapx[cachex+wayx[i]][cachey+wayy[i]]-65][0][1]<<" Timex= "<<timex[tail]<<" X= "<<cachex<<" Y= "<<cachey<<endl;
					}
				}
				else if (mapx[cachex+wayx[i]][cachey+wayy[i]]!='#' && checked[cachex+wayx[i]][cachey+wayy[i]]==false)
				{
					tail++;
					quex.push(cachex+wayx[i]); quey.push(cachey+wayy[i]);
					timex[tail]=timex[head]+1;
					checked[cachex+wayx[i]][cachey+wayy[i]]=true;
					//cout<<"X= "<<cachex+wayx[i]<<" Y= "<<cachey+wayy[i]<<" Timex= "<<timex[tail]<<endl;
				}
			}
		quex.pop(); quey.pop();
	}
	return 0; 
}


其实这个题处理好了传送门,你会发现,其实不难……(输出调试大法好)

记得用checked数组标记已经访问的点和传送门,要不无限使用传送门


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值