高中OJ1432. 输油管道

*:极其简单;

**:无需动笔;

***:需要深究细论;

****:要看题解;

*****:多次看题解,并多次问人;

******:需要加以代码分析;


题目: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太多,不过这道有点码农的题目,也要有耐心啊!


本题难度:***

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值