传送门
这道题就是平常的建墙法,但是有些题解连样例都过不了,于是我就出了这篇题解。
建墙法:顾名思义就是在图中建墙。这道题说是要绕森林一圈,而搜索找的是最短路,明显会错。既然程序不会主动地绕远路,所以要建墙,被迫使程序走到墙的另一边,又不穿墙。
举个栗子(下图为样例):
先看建墙:
if(sx>=ex&&sy==ey)//出生点在墙里 sx,sy表示初始位置
{
e1y++;//现在ex,ey表示第一面墙的坐标
for(int i=e1y;i<=m;i++) bol[e1x][i]=1;//建一排到底的墙
flag=1;
}
else
{
ex++;//同上
for(int i=ex;i<=n;i++) bol[i][ey]=1;//建一列到底的墙
}
if
中的内容是判断建的墙是否会与出生点重合;如果没有if
,不仅墙旁边只用1步就到达,你也被卡在墙里了。
下面两张图中, X X X 代表出生点,黄色的是墙,红色的是墙。
这是没有if
:
如果有if
,那么图是这样的:
避免了卡在墙里,else
中就是建普通的竖墙。
再看最终的答案:
if(!flag)
printf("%d",min(vis[ex-1][ey-1],min(vis[ex][ey-1],vis[ex+1][ey-1]))+vis[ex-1][ey+1]+2);//竖着建墙
else printf("%d",min(vis[e1x-1][e1y-1],vis[e1x-1][e1y])+min(vis[e1x+1][e1y-1],vis[e1x+1][e1y])+2);//横着建墙
先看竖着建墙时:
对于这道题,求的是这个环的长度,墙左右两边的数表示黑线的长度。
左边:min(vis[ex-1][ey-1],min(vis[ex][ey-1],vis[ex+1][ey-1]))
右边:vis[ex-1][ey+1]
为什么右边就这么点? 因为第一面墙的右上角肯定是路,所以肯定比再往下的两个点优。
再看横着建墙:
虽然找的是最右的,但可能并列的会一样长。所以不光找前一列,还要找后一列。为什么 + 2 +2 +2 呢?因为要算上墙和出生点两个单位。
这个程序主要区分:出生点是否在最后一棵树下面。
上代码:
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
struct node
{
int x,y;
};
string s;
int n,m,sx,sy,ex,ey,e1x,e1y;
int vis[51][51