传送门
题意:
给定h行w列的图表,其中部分位置有磁铁,人物会在磁铁四周((x+1,y),(x-1,y),(x,y+1),(x,y-1))停止,某点的自由度定义为从该点出发最多可到的方块数目 可以走重复路
前置例题:
求连通块大小
洛谷P1141
思路:
由自由度的定义联想到连通块的大小,从而决定用BFS求解。
本题和模板题的区别在于和磁铁相邻的空白块可以被不止一个互不连通的连通块包含,单独记录此类边界块并更新vis标记即可
code:
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
const int MAXN=1005;
char a[MAXN][MAXN];
int ans[MAXN][MAXN],vis[MAXN][MAXN];
#define f first
#define s second
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
int mx=0;
int n,m;
void bfs(int xf,int yf){
queue<pair<int,int> >q;
vector<pair<int,int> >v;
q.push({xf,yf});
vis[xf][yf]=1;
int res=1;
while(!q.empty()){
auto tt=q.front();
q.pop();
int x=tt.f,y=tt.s;
// cerr<<x<<' '<<y<<endl;
int ff=1;
for(int i=0;i<4;i++){
int xx=x+dx[i],yy=y+dy[i];
if(xx<1 || xx>n || yy<1 || yy>m)continue;
if(a[xx][yy]=='#'){//如果是边界块
ff=0;
v.push_back({x,y});
}
}
if(ff){
for(int i=0;i<4;i++){
int xx=x+dx[i],yy=y+dy[i];
if(xx<1 || xx>n || yy<1 || yy>m || vis[xx][yy] || a[xx][yy]=='#')continue;
vis[xx][yy]=1;
q.push({xx,yy});
// cerr<<xx<<' '<<yy<<endl;
res++;
}
}
}
mx=max(res,mx);
// cerr<<res<<endl;
for(auto i:v){//将边界块标记进行清洗
int x=i.f,y=i.s;
vis[x][y]=0;
}
return ;
}
void sol(){
cin>>n>>m;
string s;
for(int i=1;i<=n;i++){
cin>>s;
for(int j=1;j<=m;j++){
a[i][j]=s[j-1];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(a[i][j]!='#' && !vis[i][j]){
bfs(i,j);
}
}
}
cout<<mx<<endl;
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int t;
// cin>>t;
t=1;
while(t--){
sol();
}
}