The Grove
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 941 | Accepted: 462 |
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):
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.
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).
Lines 2..R+1: Line i+1 describes row i with C characters (with no spaces between them).
Output
Line 1: The single line contains a single integer which is the smallest number of steps required to circumnavigate the grove.
Sample Input
6 7 ....... ...X... ..XXX.. ...XXX. ...X... ......*
Sample Output
13
Source
USACO 2006 January Silver
题意:从起点出发绕着树林走一圈回到起点,求最少的步数,树林中间不会有洞
思路:最短路径第一想法便是bfs,但这题要围着走一圈,显然只用bfs不行,看了别人的博客,都用到射线法但是都没有解释,看代码理解了好半天总算想通了,讲一下我的理解。所谓的射线法也就是假想图中有一条从一树林中一个点发出射线把图分开(图一),红色的的点为假想的那条射线,由第一棵树发射出来,那么从起点到这条射线就只能顺时针后者逆时针走,正好bfs会向这两个方向搜去(图二),我们规定顺时针方向的可以一直搜到线,逆时针的只能搜到射线上面一条线。那么搜索完之后每个点的步数情况如图三(-1表示树林),我们要求的答案便是到射线的步数和到射线上一条线的步数的和的最小值,要保证选的两条线上的两个点要一部可达,另外题目要求回到起点,所以答案加上1.
AC代码:
题意:从起点出发绕着树林走一圈回到起点,求最少的步数,树林中间不会有洞
思路:最短路径第一想法便是bfs,但这题要围着走一圈,显然只用bfs不行,看了别人的博客,都用到射线法但是都没有解释,看代码理解了好半天总算想通了,讲一下我的理解。所谓的射线法也就是假想图中有一条从一树林中一个点发出射线把图分开(图一),红色的的点为假想的那条射线,由第一棵树发射出来,那么从起点到这条射线就只能顺时针后者逆时针走,正好bfs会向这两个方向搜去(图二),我们规定顺时针方向的可以一直搜到线,逆时针的只能搜到射线上面一条线。那么搜索完之后每个点的步数情况如图三(-1表示树林),我们要求的答案便是到射线的步数和到射线上一条线的步数的和的最小值,要保证选的两条线上的两个点要一部可达,另外题目要求回到起点,所以答案加上1.
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#define inf 999999999
using namespace std;
int n,m;
char str[55][55];
int vis[55][55];//记录步数的数组
struct node
{
int x;
int y;
};
queue<node> que;
node tmp,q;
int sx,sy,ex,ey;
int next[8][2]={1,0,-1,0,0,1,0,-1,1,1,1,-1,-1,1,-1,-1};//方向数组,8个方向
bool check(int x,int y,int xx,int yy)
{
if(x<1||x>n||y<1||y>m||str[x][y]=='X')
return false;
if(yy<=ey&&xx==ex&&x==xx-1)//逆时针方向的不能走超过射线
return false;
if(yy<=ey&&xx==ex-1&&x==ex)//顺时针方向不能走到射线上
return false;
return true;
}
void bfs()
{
while(que.size())
{
tmp=que.front();
que.pop();
for(int i=0;i<8;i++)
{
int tx=tmp.x+next[i][0];
int ty=tmp.y+next[i][1];
if(check(tx,ty,tmp.x,tmp.y))
{
q.x=tx;
q.y=ty;
vis[tx][ty]=vis[tmp.x][tmp.y]+1;
str[tx][ty]='X';
que.push(q);
}
}
}
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
int flag=1;
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
{
scanf("%s",str[i]+1);
for(int j=1;j<=m;j++)
{
if(str[i][j]=='X')
{
if(flag)//记录第一个出现的树的坐标
ex=i,ey=j,flag=0;
}
if(str[i][j]=='*')//记录起点
sx=i,sy=j;
}
}
tmp.x=sx;
tmp.y=sy;
que.push(tmp);
str[sx][sy]='X';
bfs();
int ans=inf;
for(int i=1;i<ey;i++)//找到最优解
{
ans=min(ans,vis[ex][i]+vis[ex-1][i+1]);
ans=min(ans,vis[ex][i]+vis[ex-1][i]);
if(i!=1)ans=min(ans,vis[ex][i]+vis[ex-1][i-1]);
}
ans+=1;
printf("%d\n",ans);
}
return 0;
}