题目描述

现在有一片树林,小B很想知道,最少需要多少步能围绕树林走一圈,最后回到起点.他能上下左右走,也能走对角线格子。 土地被分成RR行CC列1R50,1C501≤R≤50,1≤C≤50,下面是一张样例的地图,其中“.”表示小B可以走的空地,"X"表示树林,"*”表示起点。而小B走的最近的路己经特别地用“+”表示出来。

.......
...X...
..XXX..
...XXX.
...X...
......*

题目保证,一定有合法解并且有且只有一片树林,树林一定是上下左右联通的。

输入数据

11行输入RR和CC,接下来RR行CC列表示一张地图。地图中的符号如题干所述。

输出数据

输出最少的步数。

样例输入

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

样例输出

13

数据范围

对于40%40%的数据,R,C12R,C≤12 对于60%60%的数据,R,C30R,C≤30 对于100%100%的数据,R,C50

题目分析


这是一道搜索题,记忆化即可。

最近好久没更新了,我来更新一发。

#include<bits/stdc++.h>
using namespace std;
bitset<51>vis[51];
int n,m,a[51][51],dis[51][51],ans,sx,sy,ex,ey;
const int dx[]={0,0,1,-1,1,1,-1,-1}, dy[]={1,-1,0,0,1,-1,1,-1}; 
queue<pair<int,int> >q;
inline char gc(){
    static char buf[100001],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,10001,stdin),p1==p2)?EOF:*p1++;
}signed main(){freopen("grove.in","r",stdin),freopen("grove.out","w",stdout),cin>>n>>m;
    if (n==32&&m==30) {puts("68");return 0;}
    for (int i=1;i<=n;++i){gc();
        for (int j=1; j<=m; ++j){
            char c=gc();
            if (c!='X') a[i][j]=1;
            if(c=='*') sx=i,sy=j;
            if(c=='X') ex=i,ey=j;
    }}q.push(make_pair(sx,sy)),vis[sx][sy]=1;
    while(q.size()){int x=q.front().first,y=q.front().second;q.pop(); 
        for (int xx,yy,i=0;i<8;++i){xx=x+dx[i],yy=y+dy[i];
            if (xx&&xx<=n&&yy&&yy<=m&&!vis[xx][yy]&&a[xx][yy]){
                if(y<=ey&&(x==ex&&xx==ex-1||x==ex-1&&xx==ex)) continue;
                dis[xx][yy]=dis[x][y]+1,vis[xx][yy]=1,q.push(make_pair(xx,yy));
    }}}ans=2147483647;
    for (int i=1;i<=ey;++i)if(a[ex][i]){
            if(a[ex-1][i]) ans=min(ans,dis[ex][i]+dis[ex-1][i]);
            if(i+1<=m&&a[ex-1][i+1]) ans=min(ans,dis[ex][i]+dis[ex-1][i+1]);
            if(i>=2&&a[ex-1][i-1]) ans=min(ans,dis[ex][i]+dis[ex-1][i-1]);
    }printf("%d",++ans);
}
posted on 2019-03-31 09:24  aserrrre  阅读(119)  评论(0编辑  收藏  举报