bfs 三维标记

做训练赛遇到的一道题,感觉很好。

大致题意:

现在给你一个地图n*m,' . '代表是空格子,' * '代表是有柱子阻隔。现在你站在a点,要走到b点。走的时候要遵循一个规则:必须走相邻的格子,如果相邻的格子为有柱子格子,那么这个格子与有柱子的格子相邻的边起火,如果一个有柱子的格子的两条或者多条不同的边起火了,那么这个格子就会变成空格子。现在问你,你是否能从a点走到b点。

n<=500,m<=500.

大致思路:

首先想到是bfs,但是这个起火的状态怎么表示呢?而且我们注意到一个空格子是可以反复走的。

我的思路是定义一个三维数组v[x][y][i],代表想x,y所在的格子是否往i反向走过。(i四种状态,上下左右)如果x,y向i方向走之后所在的格子是柱子格子,那么就让这个柱子格子的check值加1(我们可以再开个数组check,代表柱子格子的边有几条着火,当check[x][y]的值为2时,就把它变成’ . ')。如果不是,那么就正常走。

每次走之后我们都把v当前的[x][y][i]记录为1,代表这个格子已经走过旁边的某个格子了,以后不用再走了。这样就避免了重复入队。

代码:

#include
#include
#include
#include
#include
#include
using namespace std;
char rc[550][550];
int vis[550][550][4];
int check[550][550];
int r,c;
int dis[4][2]= {{1,0},{-1,0},{0,1},{0,-1}};
typedef struct node
{
    int x;
    int y;

} node;
mapM;
int bfs(node a,node b)
{
    queueQ;
    Q.push(a);
    int flag=1;
    while(!Q.empty())
    {
        //printf("***\n");
        node aa=Q.front();
        if(aa.x==b.x&&aa.y==b.y&&rc[aa.x][aa.y]!='*')return 1;
        Q.pop();
        for(int i=0; i<4; i++)
        {
            int xx=aa.x+dis[i][0];
            int yy=aa.y+dis[i][1];

            if(xx>=1&&xx<=r&&yy>=1&&yy<=c)
            {
                if(rc[xx][yy]=='.'&&!vis[aa.x][aa.y][i])
                {
                    vis[aa.x][aa.y][i]=1;
                    node k;
                    k.x=xx;
                    k.y=yy;
                    Q.push(k);
                }
                else
                {
                    if(!vis[aa.x][aa.y][i])
                    {
                        vis[aa.x][aa.y][i]=1;
                        check[xx][yy]++;
                        if(check[xx][yy]==2)
                        {
                            rc[xx][yy]='.';
                            node k;
                            k.x=xx;
                            k.y=yy;
                            Q.push(k);
                        }

                    }
                }

            }
        }
    }
    return 0;

}
int main()
{
    int t;
    while(~scanf("%d",&t))
    {
        while(t--)
        {
            scanf("%d%d",&r,&c);
            memset(vis,0,sizeof(vis));
            memset(check,0,sizeof(check));
            for(int i=1; i<=r; i++)
            {
                for(int j=1; j<=c; j++)
                {
                    cin>>rc[i][j];
                }
            }
            node st,ed;
            cin>>st.x>>st.y>>ed.x>>ed.y;
            if(bfs(st,ed))
            {
                printf("YES\n");
            }
            else
                printf("NO\n");
        }

    }
}


你可能感兴趣的:(水题)