*:极其简单;
**:无需动笔;
***:需要深究细论;
****:要看题解;
*****:多次看题解,并多次问人;
******:需要加以代码分析;
题目:https://jzoj.net/senior/#main/show/1432
这道题,因为数据只存在一条路径,所以可以按照原图去模拟,注意一点:
一个管道如果是‘+’号,则四周不可能有'.'
一个管道如果是‘1’,则不可能右边或下面缺一个与之相连的管道…………
总之,意思就是一个管道的四周不能有缺口。
那么,我们按照图一直去模拟,找到一个缺口时直接判断这个缺口四周管道的特性,理性分析得出答案。
代码:
const
dx:Array[1..4] of longint=(-1,0,0,1);
dy:array[1..4] of longint=(0,-1,1,0);
var
ans:array[1..4] of boolean;
bz:array[1..25,1..25] of boolean;
b:array['+'..'|',1..4] of boolean;
d:Array[1..10000,1..2] of longint;
ch:array[1..25,1..25] of char;
n,m,i,j,x,y,head,tail,xx,yy,xxx,yyy:longint;
begin
readln(n,m);
for i:=1 to n do
begin
for j:=1 to m do
begin
read(ch[i,j]);
if ch[i,j]='M' then
begin
x:=i;
y:=j;
end;
end;
readln;
end;
fillchar(bz,sizeof(bz),true);
bz[x,y]:=false;
b['|',1]:=true; b['|',4]:=true; b['-',2]:=true; b['-',3]:=true; b['+',1]:=true; b['+',2]:=true; b['+',3]:=true; b['+',4]:=true;
b['1',3]:=true; b['1',4]:=true; b['2',1]:=true; b['2',3]:=true; b['3',1]:=true; b['3',2]:=true; b['4',2]:=true; b['4',4]:=true;
heaD:=0;
tail:=1;
d[1,1]:=x;
d[1,2]:=y;
for i:=1 to 4 do
begin
xx:=x+dx[i]; yy:=y+dy[i];
if (xx=0) or (xx>n) or (yy=0) or (yy>m) then continue;
if ch[xx,yy]<>'.' then b['M',i]:=true;
end;
while head<tail do
begin
inc(head);
for i:=1 to 4 do
if b[ch[d[head,1],d[head,2]],i] then
begin
xx:=d[head,1]+dx[i]; yy:=d[head,2]+dy[i];
if (xx=0) or (xx>n) or (yy=0) or (yy>m) then continue;
if ch[xx,yy]='.' then
begin
write(xx,' ',yy,' ');
for j:=1 to 4 do
begin
xxx:=xx+dx[j]; yyy:=yy+dy[j];
if (xxx=0) or (xxx>n) or (yyy=0) or (yyy>m) then continue;
if (ch[xxx,yyy]<>'.') and b[ch[xxx,yyy],5-j] then ans[j]:=true;
end;
if ans[1] and ans[2] and ans[3] and ans[4] then writeln('+') else
if ans[1] and ans[4] then writeln('|') else
if ans[2] and ans[3] then writeln('-') else
if ans[3] and ans[4] then writeln('1') else
if ans[1] and ans[3] then writeln('2') else
if ans[1] and ans[2] then writeln('3') else
if ans[2] and ans[4] then writeln('4');
halt;
end
else
begin
if bz[xx,yy] and (b[ch[xx,yy],5-i]) then
begin
bz[xx,yy]:=false;
inc(tail);
d[tail,1]:=xx;
d[tail,2]:=yy;
end;
end;
end;
end;
end.
但是这样模拟的话显然编程复杂度是较高的,这个代码里也已经写的很精简了,但还是免不了4000+
我们可以考虑一种新的思路,是否不模拟,直接找出缺口?
理性分析一下,应该是有规律的;
根据上面分析的管道周围不可能有缺口,我们可以如下讨论:对于一个‘.’,我们假设它的管道是什么,然后依次理性判断周围的管道就可以了。
代码:
var
ch:array[0..25,0..25] of char;
n,m,i,j:longint;
a,b,c,d:char;
begin
readln(n,m);
for i:=1 to n do
begin
for j:=1 to m do
begin
read(ch[i,j]);
end;
readln;
end;
for i:=1 to n do
for j:=1 to m do
begin
if ch[i,j]<>'.' then continue;
a:=ch[i-1,j]; b:=ch[i,j-1]; c:=ch[i,j+1]; d:=ch[i+1,j];
if ((a='|') or (a='+') or (a='1') or (a='4')) and ((b='-') or (b='+') or (b='1') or (b='2')) and ((c='-') or (c='+') or (c='3') or (c='4')) and ((d='|') or (d='+') or (d='2') or (d='3')) then writeln(i,' ',j,' ','+') else
if ((a='+') or (a='|') or (a='4') or (a='1')) and ((d='+') or (d='|') or (d='2') or (d='3')) then writeln(i,' ',j,' ','|') else
if ((b='+') or (b='1') or (b='2') or (b='-')) and ((c='+') or (c='3') or (c='4') or (c='-')) then writeln(i,' ',j,' ','-') else
if ((c='-') or (c='+') or (c='3') or (c='4')) and ((d='|') or (d='+') or (d='2') or (d='3')) then writeln(i,' ',j,' ','1') else
if ((a='+') or (a='|') or (a='1') or (a='4')) and ((c='-') or (c='3') or (c='+') or (c='4')) then writeln(i,' ',j,' ','2') else
if ((a='+') or (a='|') or (a='1') or (a='4')) and ((b='-') or (b='2') or (b='1') or (b='+')) then writeln(i,' ',j,' ','3') else
if ((b='-') or (b='+') or (b='1') or (b='2')) and ((d='|') or (d='+') or (d='2') or (d='3')) then writeln(i,' ',j,' ','4');
end;
end.
虽然if太多,不过这道有点码农的题目,也要有耐心啊!
本题难度:***