The Grove



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.

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).

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
题意:‘*’为起点,X为森林,Bessie要绕森林一周回到起点
思路:求最短路首先想到BFS,接着怎么才能绕森林一圈还不会直接回到起点呢!先预处理x,已某一个x为一个射线,超过以X为射线
的时候不能往回搜,当搜到在该射线上时,就标记可以回到起点,否则不能回到起点,这样不仅可以绕森林一圈,而且还可以不会一开始就
回到起点!
#include <iostream>
#include <queue>
#include <algorithm>
#include <string.h>

using namespace std;

struct node
{
    int x,y,step;
    int f;
};

int n,m,sx,sy;
int Map[55][55],flag[55][55][2];
int dir[8][2] = {-1,-1,-1,0,-1,1,0,-1,0,1,1,-1,1,0,1,1};

int bfs( )
{
    queue<node>q;
    node now,next;
    now.x = sx;
    now.y = sy;
    now.f = 0;
    now.step = 0;
    flag[sx][sy][0] = 1;
    q.push(now);
    while(!q.empty())
    {
        now = q.front();
        q.pop();
        if(now.x == sx && now.y == sy && flag[now.x][now.y][1])
            return now.step;
        for(int i=0;i<8;i++)
        {
            int xx = now.x + dir[i][0];
            int yy = now.y + dir[i][1];
//            if(xx < 1 || xx >n || yy < 1 || yy > m)
//                continue;
            if(!Map[xx][yy])
                continue;
            if((Map[xx][yy] == 2 || Map[now.x][now.y] == 2) && yy<now.y)//当前在射线上或下一个点在射线上,从右到左,不能像左走
                continue;
//            cout<<"xx="<<xx<<" "<<"yy="<<yy<<endl;
            if(Map[now.x][now.y] == 2)//找到该射线,更新点!
            {
                if(!flag[xx][yy][1])
                {
                    flag[xx][yy][1] = 1;
                    next.x = xx;
                    next.y = yy;
                    next.f = 1;
                    next.step = now.step + 1;
                    q.push(next);
                }
            }
            else
                {
                    if(!flag[xx][yy][now.f])
                    {
                        flag[xx][yy][now.f] = 1;
                        next.x = xx;
                        next.y = yy;
                        next.step = now.step + 1;
                        next.f = now.f;
                        q.push(next);
                    }
                }
//            q.push(next);
        }
    }
    return -1;
}

int main()
{
    cin>>n>>m;
    char ch;
    memset(flag,0,sizeof(flag));
    memset(Map,0,sizeof(Map));
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cin>>ch;
            if(ch == 'X')
                Map[i][j] = 0;
           else
           {
               Map[i][j] = 1;
               if(ch == '*')
               {
                   sx= i;
                   sy = j;
               }
           }
        }
    }
    int b,c = -1;
    for(int i=1;i<=n&&c<0;i++)
    {
        for(int j=1;j<=m&&c<0;j++)
        {
            if(!Map[i][j])
            {
                b=i;
                c=j;
            }
        }
    }
    for(int i=1;i<b;i++)
    {
        Map[i][c] = 2;
    }
//    for(int i=1;i<=n;i++)
//    {
//        for(int j=1;j<=m;j++)
//            cout<<Map[i][j]<<" ";
//        cout<<endl;
//    }
    cout<<bfs()<<endl;
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值