1656: [Usaco2006 Jan] The Grove 树木 BFS+射线阻隔


1656: [Usaco2006 Jan] The Grove 树木

Time Limit: 5 Sec   Memory Limit: 64 MB
Submit: 258   Solved: 168
[ 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.

    输出最少的步数.

Sample Input

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

Sample Output

13

HINT

Source



人环绕树林一圈,则在一个点发出射线阻隔,然后bfs,特判越线状况.


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int INF = 1e9;

const int dx[8]={0,0,1,-1,1,1,-1,-1},dy[8]={1,-1,0,0,1,-1,1,-1};
struct node{
    int x;
    int y;
};



int mm[51][51];
string s;
int n,m,sx,sy;

int x=-1,y;
int bfs()
{
    node cur,nex;
    queue<node> q;
    cur.x = sx;
    cur.y = sy;
    q.push(cur);
    while(!q.empty())
    {
        cur = q.front();
        q.pop();
        for(int i=0;i<8;i++)
        {
            int xx = cur.x+dx[i];
            int yy = cur.y+dy[i];

            if(xx<0||xx>=n||yy<0||yy>=m||mm[xx][yy]!=0)
            {
                continue;
            }
            if(cur.y<=y &&cur.x==x    && xx==x-1) continue;//从下向上越线
            if(cur.y<=y &&cur.x==x-1  && xx==x) continue;//从上向下越线
            mm[xx][yy]=mm[cur.x][cur.y]+1;
            nex.x = xx;
            nex.y = yy;
            q.push(nex);

        }
    }
}



int main()
{
//    freopen("data.txt","r",stdin);
    ios_base::sync_with_stdio(false);
    cin >> n>>m;
    for(int i = 0;i < n;i ++)
    {
        cin >> s;
        for(int j = 0;j < m;j ++)
        {
            if(s[j]=='X')
            {
                mm[i][j]=-1;
                if(x==-1)
                {
                    x=i;
                    y=j;
                }
            }
            else if(s[j]=='*')
            {
                sx=i;
                sy=j;
            }
        }
    }
    bfs();
    int ans=INF;
    //在线上遍历各点
    for (int i=y-1;i>=0;i--)
    {
        if (mm[x][i]+mm[x-1][i]<ans) ans=mm[x][i]+mm[x-1][i];
        if (mm[x][i]+mm[x-1][i+1]<ans) ans=mm[x][i]+mm[x-1][i+1];
        if (i) if (mm[x][i]+mm[x-1][i-1]<ans) ans=mm[x][i]+mm[x-1][i-1];
    }
    cout <<ans+1<<endl;
    return 0;
}

















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值