AtCoder Beginner Contest 351 D - Grid and Magnet

文章讨论了一个关于在一个由网格和磁铁组成的环境中,穿着铁甲的Takahashi如何在受限制的移动条件下计算无磁铁细胞的最大自由度。通过深度优先搜索(DFS)和广度优先搜索(BFS)算法解决此问题,考虑了磁铁对移动的限制。
摘要由CSDN通过智能技术生成

Time Limit: 2 sec / Memory Limit: 1024 MB

Score:425 points

Problem Statement

There is a grid of 𝐻H rows and 𝑊W columns. Some cells (possibly zero) contain magnets.
The state of the grid is represented by 𝐻H strings 𝑆1,𝑆2,…,𝑆𝐻of length 𝑊. If the 𝑗j-th character of 𝑆𝑖​ is #, it indicates that there is a magnet in the cell at the 𝑖i-th row from the top and 𝑗j-th column from the left; if it is ., it indicates that the cell is empty.

Takahashi, wearing an iron armor, can move in the grid as follows:

  • If any of the cells vertically or horizontally adjacent to the current cell contains a magnet, he cannot move at all.
  • Otherwise, he can move to any one of the vertically or horizontally adjacent cells.
    However, he cannot exit the grid.

For each cell without a magnet, define its degree of freedom as the number of cells he can reach by repeatedly moving from that cell. Find the maximum degree of freedom among all cells without magnets in the grid.

Here, in the definition of degree of freedom, "cells he can reach by repeatedly moving" mean cells that can be reached from the initial cell by some sequence of moves (possibly zero moves). It is not necessary that there is a sequence of moves that visits all such reachable cells starting from the initial cell. Specifically, each cell itself (without a magnet) is always included in the cells reachable from that cell.

Constraints

  • 1≤H,W≤1000
  • 𝐻 and 𝑊 are integers.
  • 𝑆𝑖 is a string of length 𝑊 consisting of . and #.
  • There is at least one cell without a magnet.

Input

The input is given from Standard Input in the following format:

𝐻H 𝑊W
𝑆1
𝑆2
⋮
𝑆𝐻

Output

Print the maximum degree of freedom among all cells without magnets.

Sample Input 1Copy

Copy

3 5
.#...
.....
.#..#

Sample Output 1Copy

Copy

9

Sample Input 2Copy

Copy

3 3
..#
#..
..#

Sample Output 2Copy

Copy

1

For any cell without a magnet, there is a magnet in at least one of the adjacent cells.
Thus, he cannot move from any of these cells, so their degrees of freedom are 1.
Therefore, print 1.

翻译:

思路:

如果没有限制,就是普通的搜索了,暴力跑就好了。加上这个限制,如果我们像连通块一样,提前把某个格子跑到,并且因为 周围上下左右有一个#就不能移动,提前打上标记。后面其实从其他位置出发也能跑到这个格子,这个格子的计数就少了。
那如果我们跑每个点的时候,都对整张地图的vis 标记memset 重置一下,那么总的时间复杂度又太大了。
注意vis,每次进行bfs或者dfs时,要选用没有被任何连通块所访问过的点。

DFS求解

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

typedef long long ll;

const int N=1005;
int cnt,n,m,num,ans;
int dx[4]= {0,1,0,-1};
int dy[4]= {-1,0,1,0};
char g[N][N];
int vis[N][N];

bool check(int x,int y) // 检查当前位置是否可以移动
{
    for(int i=0; i<4; i++)
    {
        int nx=x+dx[i];
        int ny=y+dy[i];
        if(g[nx][ny]=='#') return false; // 如果相邻位置有磁铁,则无法移动
    }
    return true;
}

void dfs(int x,int y,int id)
{
    cnt++;
    vis[x][y]=id;
    if(!check(x,y)) return;
    for(int i=0; i<4; i++)
    {
        int nx=x+dx[i];
        int ny=y+dy[i];
        if(nx<1 || nx>n || ny<1 || ny>m) continue;
        if(vis[x][y]==vis[nx][ny]) continue;//(nx,ny) 在此连通块下已经访问过了
        dfs(nx,ny,id);
    }
}

int main()
{
    cin>>n>>m;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=m; j++)
            cin>>g[i][j];
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            if(g[i][j]=='.' && !vis[i][j])
            {
                cnt=0;
                ++num;
                dfs(i,j,num);
                ans=max(ans,cnt);
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}



BFS求解:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>

using namespace std;

typedef long long ll;

const int N=1005;

char g[N][N];
int vis[N][N];

int n,m;
int num,ans,cnt;

int dx[4]={0,-1,0,1};
int dy[4]={1,0,-1,0};

struct node
{
    int x;
    int y;
    int z;
};

bool check(int x,int y)
{
    for(int i=0;i<4;i++)
    {
        int nx=x+dx[i];
        int ny=y+dy[i];
        if(g[nx][ny]=='#') return false;
    }
    return true;
}

void bfs(int x,int y,int id)
{
    queue<node> q;
    vis[x][y]=id;
    cnt++;
    q.push({x,y,id});
    while(!q.empty())
    {
        node t=q.front();
        q.pop();
        int tx=t.x;
        int ty=t.y;
        int tz=t.z;
        if(!check(tx,ty)) continue;
        for(int i=0;i<4;i++ )
        {
            int X=tx+dx[i];
            int Y=ty+dy[i];
            if(X<1 || X>n || Y<1 || Y>m) continue;
            if(vis[X][Y]== vis[tx][ty]) continue;
            vis[X][Y]=tz;
            cnt++;
            q.push({X,Y,tz});
        }
    }
}

void solve()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            cin>>g[i][j];
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(g[i][j]=='.' && !vis[i][j])
            {
                cnt=0;
                num++;
                bfs(i,j,num);
                ans=max(ans,cnt);
            }
        }
    }
    cout<<ans<<endl;
}

int main()
{
    solve();
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值