Overfencing (maze1)[USACO 2.4.2]

{BFS水过。。。}

program maze1;

const
	dx:array [1..4] of -1..1=(-1,0,1,0);
	dy:array [1..4] of -1..1=(0,1,0,-1);

type atp=record
		x,y,depth:longint;
	end;

var
	dep1,dep2,dep:array [0..201,0..201] of longint;//dep1[x,y]记录从第一个门到(x,y)点的最短距离,dep2[x,y]记录从第二个门到(x,y)点的最短距离,dep[x,y]记录dep1和dep2的最小值。
	b:array [0..201,0..201] of boolean;
	que:array [0..1000000] of atp;//que为BFS队列。
	w,h,sx1,sy1,sx2,sy2,head,tail:longint;//sx1,sy1分别代表第一个门的横纵坐标,同理sx2,sy2代表第二个门的横纵坐标。
	a:array [0..201,0..201] of 0..2;
	
procedure init;
var
	i,j:longint;
	t:char;
begin
	//我是采用抽象为点的做法做的,不管当前位置是加号或是减号还是竖线全为1,其它除了门之外能走的地方全是0,门是2。
	readln(w,h);
	for i:=2*h+1 downto 1 do
		begin
			for j:=1 to 2*w+1 do
				begin
					read(t);
					case t of
						'+':a[j,i]:=1;
						'-':a[j,i]:=1;
						'|':a[j,i]:=1;
						' ':begin
								if (i=2*h+1) or (j=2*w+1) or (j=1) or (i=1) then 
									begin
										a[j,i]:=2;
										if sx1=0 then 
											begin
												sx1:=j;
												sy1:=i;
											end
										else 
											begin
												sx2:=j;
												sy2:=i;
											end;
									end
								else a[j,i]:=0;
							end;
					end;
				end;
			readln;
		end;
end;
	
function minest(x,y:longint):longint;
begin
	if x>y then exit(y) else exit(x);
end;

procedure bfs;
var
	max,tx,ty,i,j:longint;
begin
	fillchar(que,sizeof(que),0);
	head:=0;
	tail:=1;
	fillchar(b,sizeof(b),false);
	b[sx1,sy1]:=true;
	que[1].x:=sx1;
	que[1].y:=sy1;
	que[1].depth:=1;
	while head<=tail do
		begin
			inc(head);
			for i:=1 to 4 do
				begin
					tx:=que[head].x+dx[i];
					ty:=que[head].y+dy[i];
					if (tx<=2*w+1) and (tx>=1) and (ty>=1) and (ty<=2*h+1) and (not b[tx,ty]) and (a[tx,ty]=0) then
						begin
							inc(tail);
							b[tx,ty]:=true;
							que[tail].x:=tx;
							que[tail].y:=ty;
							que[tail].depth:=que[head].depth+1;
							dep1[tx,ty]:=que[tail].depth;//每次都记录一下大门到当前位置的距离
						end;
				end;
		end;
	fillchar(que,sizeof(que),0);
	head:=0;
	tail:=1;
	fillchar(b,sizeof(b),false);
	b[sx2,sy2]:=true;
	que[1].x:=sx2;
	que[1].y:=sy2;
	que[1].depth:=1;
	while head<=tail do
		begin
			inc(head);
			for i:=1 to 4 do
				begin
					tx:=que[head].x+dx[i];
					ty:=que[head].y+dy[i];
					if (tx<=2*w+1) and (tx>=1) and (ty>=1) and (ty<=2*h+1) and (not b[tx,ty]) and (a[tx,ty]=0) then
						begin
							inc(tail);
							b[tx,ty]:=true;
							que[tail].x:=tx;
							que[tail].y:=ty;
							que[tail].depth:=que[head].depth+1;
							dep2[tx,ty]:=que[tail].depth;//同上。
						end;
				end;
		end;
	max:=-maxlongint;
	for i:=2*h+1 downto 1 do
		begin
			for j:=1 to 2*w+1 do
				begin
					if (a[j,i]=0) and (i mod 2=0) and (j mod 2=0) then 
						begin
							dep[j,i]:=minest(dep1[j,i],dep2[j,i]);//就卡在这了,题意没理解清,先求当前位置是走第一个大门近还是走第二个大门近,先刷一遍。
							if dep[j,i]>max then max:=dep[j,i];//再在所有的位置中找一个最大值即为所求。
						end;
				end;
		end;
	writeln(max shr 1);
end;

begin
	assign(input,'maze1.in'); reset(input);
	assign(output,'maze1.out'); rewrite(output);

	init;
	bfs;

	close(input); close(output);
end.


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值