usaco Overfencing 穿越栅栏(BFS)

Overfencing 穿越栅栏
农夫 John 在外面的田野上搭建了一个巨大的用栅栏围成的迷宫.幸运的是,他在迷宫的边界上留出
了两段栅栏作为迷宫的出口.更幸运的是,他所建造的迷宫是一个“完美的”迷宫:即你能从迷宫中
的任意一点找到一条走出迷宫的路.
给定迷宫的宽 W(1<=W<=38)及长 H(1<=H<=100).
2*H+1行,每行2*W+1的字符以下面给出的格式表示一个迷宫.然后计算从迷宫中最“糟糕”的那一
个点走出迷宫所需的步数.(即使从这一点以最优的方式走向最靠近的出口,它仍然需要最多的步
数)当然了,牛们只会水平或垂直地在 X 或 Y 轴上移动,他们从来不走对角线.每移动到一个新的方
格算作一步(包括移出迷宫的那一步)
这是一个 W=5,H=3 的迷宫:
+-+-+-+-+-+
| |
+-+ +-+ + +
| | | |
+ +-+-+ + +
| | |
+-+ +-+-+-+
如上图的例子,栅栏的柱子只出现在奇数行或奇数列.每个迷宫只有两个出口.
PROGRAM NAME: maze1
INPUT FORMAT
第一行: W 和 H(用空格隔开)
第二行至第 2*H+2 行: 每行 2*W+1 个字符表示迷宫
SAMPLE INPUT (file maze1.in)
5 3
+-+-+-+-+-+
| |
+-+ +-+ + +
| | | |
+ +-+-+ + +
| | |
+-+ +-+-+-+
OUTPUT FORMAT
输出一个单独的整数,表示能保证牛从迷宫中任意一点走出迷宫的最小步数.
SAMPLE OUTPUT (file maze1.out)

9

把两个门加到队列里一起bfs用setup记录达到某点的步数(顺便可以当vis数组使用防止重走)最后到达那个最远点的步数就是要求的答案。我在判断到门的时候把门转为迷宫中的格子然后加入队列并使那点的setup为1.

/*
ID: jinbo wu
TASK:maze1
LANG:C++
*/
#include<bits/stdc++.h>
using namespace std;
char a[250][100];
int dir[4][2]={2,0,0,2,-2,0,0,-2};
int ex[2],ey[2];
int w,h;
struct node
{
	int x,y;
}temp;
int setup[250][100];
bool can(int x,int y,int c,int d)
{
	if(c>=0&&c<2*h+1&&d>=0&&d<2*w+1&&a[x][y]==' ')
	return true;
	return false;
}
queue<node> q;
int bfs()
{
	node t1,t2;
	int ans=0;
	while(!q.empty())
	{
		t2=q.front();
		q.pop();
		if(ans<setup[t2.x][t2.y])
		ans=setup[t2.x][t2.y];
		for(int i=0;i<4;i++)
		{
			t1.x=t2.x+dir[i][0];
			t1.y=t2.y+dir[i][1];
			int xx=t2.x+dir[i][0]/2;
			int yy=t2.y+dir[i][1]/2;
			if(can(xx,yy,t1.x,t1.y)&&!setup[t1.x][t1.y])
			{
				setup[t1.x][t1.y]=setup[t2.x][t2.y]+1;
				q.push(t1);
			}
		}
	}
	return ans;
	
}
int main()
{
	freopen("maze1.in","r",stdin);
	freopen("maze1.out","w",stdout);
	cin>>w>>h;
	int l=0;
	getchar();
	for(int i=0;i<2*h+1;i++)
	{
	 for(int j=0;j<2*w+1;j++)
	 {
	 scanf("%c",&a[i][j]);
	 if(((i==0||i==2*h)||(j==0||j==2*w))&&(a[i][j]==' '))
	 {
	 	int dx=i,dy=j;
	 	if(i==0) dx+=1;
	 	if(j==0) dy+=1;
	 	if(i==2*h) dx-=1;
	 	if(j==2*w) dy-=1;
	 	temp.x=dx,temp.y=dy;
	 	setup[dx][dy]=1;
	 	q.push(temp);
	 }
     }
     getchar();
    }
    int ans=bfs();
    cout<<ans<<endl;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值