P2864 [USACO06JAN]The Grove S 题解

传送门

这道题就是平常的建墙法,但是有些题解连样例都过不了,于是我就出了这篇题解。

建墙法:顾名思义就是在图中建墙。这道题说是要绕森林一圈,而搜索找的是最短路,明显会错。既然程序不会主动地绕远路,所以要建墙,被迫使程序走到墙的另一边,又不穿墙。

举个栗子(下图为样例):

先看建墙:

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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值