# bzoj 1656: [Usaco2006 Jan] The Grove 树木 （bfs+技巧）

## 1656: [Usaco2006 Jan] The Grove 树木

Time Limit: 5 Sec   Memory Limit: 64 MB
Submit: 196   Solved: 124
[ Submit][ Status][ Discuss]

## Description

The pasture contains a small, contiguous grove of trees that has no 'holes' in the middle of the it. Bessie wonders: how far is it to walk around that grove and get back to my starting position? She's just sure there is a way to do it by going from her start location to successive locations by walking horizontally, vertically, or diagonally and counting each move as a single step. Just looking at it, she doesn't think you could pass 'through' the grove on a tricky diagonal. Your job is to calculate the minimum number of steps she must take. Happily, Bessie lives on a simple world where the pasture is represented by a grid with R rows and C columns (1 <= R <= 50, 1 <= C <= 50). Here's a typical example where '.' is pasture (which Bessie may traverse), 'X' is the grove of trees, '*' represents Bessie's start and end position, and '+' marks one shortest path she can walk to circumnavigate the grove (i.e., the answer): ...+... ..+X+.. .+XXX+. ..+XXX+ ..+X..+ ...+++* The path shown is not the only possible shortest path; Bessie might have taken a diagonal step from her start position and achieved a similar length solution. Bessie is happy that she's starting 'outside' the grove instead of in a sort of 'harbor' that could complicate finding the best path.

贝茜很想知道，最少需要多少步能围绕树林走一圈，最后回到起点．她能上下左右走，也能走对角线格子．牧场被分成R行C列(1≤R≤50，1≤C≤50)．下面是一张样例的地图，其中“．”表示贝茜可以走的空地，  “X”表示树林，  “*”表示起点．而贝茜走的最近的路已经特别地用“+”表示出来．

## Input

* Line 1: Two space-separated integers: R and C

* Lines 2..R+1: Line i+1 describes row i with C characters (with no spaces between them).

第1行输入R和C，接下来R行C列表示一张地图．地图中的符号如题干所述．

## Output

* Line 1: The single line contains a single integer which is the smallest number of steps required to circumnavigate the grove.

输出最少的步数．

6 7
.......
...X...
..XXX..
...XXX.
...X...
......*

13

## Source

[ Submit][ Status][ Discuss]

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define pa pair<int,int>
#define N 53
using namespace std;
int n,m,a[N][N],sx,sy,dis[N][N][20],can[N][N][20],vis[N][N],x[N*N],y[N*N],cnt;
int px[10]={0,1,0,-1,1,1,-1,-1},py[10]={1,0,-1,0,-1,1,-1,1};
struct data {
int x,y,sta;
};
void bfs()
{
memset(can,0,sizeof(can));
data a1; a1.x=sx; a1.y=sy;
if (vis[sx][sy]!=-1)  a1.sta=(1<<vis[sx][sy]);
else a1.sta=0;
queue<data> p; p.push(a1); can[sx][sy][a1.sta]=1;
dis[sx][sy][a1.sta]=0;
while (!p.empty()){
data now=p.front(); p.pop();
int x=now.x; int y=now.y;
for (int i=0;i<8;i++) {
int nowx=x+px[i]; int nowy=y+py[i]; int t;
if (vis[nowx][nowy]!=-1) t=now.sta|(1<<vis[nowx][nowy]);
else t=now.sta;
if (nowx<=0||nowy<=0||nowx>n||nowy>m||a[nowx][nowy]||can[nowx][nowy][t]) continue;
dis[nowx][nowy][t]=dis[x][y][now.sta]+1;
can[nowx][nowy][t]=1;
data a1; a1.x=nowx; a1.y=nowy; a1.sta=t;
p.push(a1);
}
}
}
int main()
{
freopen("input.in","r",stdin);
freopen("my.out","w",stdout);
scanf("%d%d",&n,&m);
int xmin=N; int ymin=N; int xmax=0; int ymax=0;
for (int i=1;i<=n;i++) {
char s[N]; scanf("%s",s+1);
for (int j=1;j<=m;j++) {
if (s[j]=='X') a[i][j]=1,xmin=min(xmin,i),xmax=max(xmax,i),
ymin=min(ymin,j),ymax=max(ymax,j);
if (s[j]=='*') sx=i,sy=j;
}
}
memset(vis,-1,sizeof(vis));
int mid=(ymin+ymax)/2;
for (int i=1;i<=n;i++)
if (!a[i][mid]) vis[i][mid]=0;
else break;
for (int i=n;i>=1;i--)
if (!a[i][mid]) vis[i][mid]=1;
else break;
mid=(xmin+xmax)/2;
for (int i=1;i<=m;i++)
if (!a[mid][i]) vis[mid][i]=2;
else break;
for (int i=m;i>=1;i--)
if (!a[mid][i])  vis[mid][i]=3;
else break;
/*for (int i=1;i<=n;i++)
{
for (int j=1;j<=m;j++)
cout<<vis[i][j]<<" ";
cout<<endl;
}*/
bfs();
printf("%d\n",dis[sx][sy][15]);
}


08-21 213

07-04 389
10-31 251
07-20 179
04-06
03-31 48
11-15 545
09-20 1万+
02-10 5510
07-18 323