【二进制状态表示】 城堡问题
传送门
题意
\(n\times m\)的区域,每块墙有方向,其中上北下南左西右东,\(1\)表示西墙,\(2\)表示北墙,\(4\)表示东墙,\(8\)表示南墙,每个块中一个数字\(p\)表示上述表示墙的所有数字和,如\(p=3=1+2\),有西墙和北墙,每个墙计算\(2\)次,例如,\((2,2)\)的北墙也是\((1,2)\)的南墙,有墙的不是一个连通块,求最大的连通块
数据范围
\(1\leq n,m\leq 50\)
\(0\leq P\leq 15\)
题解
-
按照二进制移位的次序,应该是左上右下
-
左对应\((0,-1)\),上对应\((-1,0)\),右对应\((0,1)\),下对应\((1,0)\)
-
数据保证了两个相邻墙的重合和不需要进行额外的判断
-
数组坐标需要特别注意
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<=n;i++)
const int N=55;
int g[N][N];
int n,m;
bool st[N][N];
int dx[4]={0,-1,0,1},dy[4]={-1,0,1,0};
int bfs(int x,int y)
{
int res=0;
queue<pair<int,int>>q;
q.push(make_pair(x,y));
st[x][y]=1;
while(q.size())
{
pair<int,int> t=q.front();
q.pop();
++res;
rep(i,0,3)
{
int tx=t.first+dx[i],ty=t.second+dy[i];
if(st[tx][ty]) continue;
if(g[t.first][t.second] >>i&1) continue;
if(tx>=1&&tx<=n&&ty>=1&&ty<=m)
{
st[tx][ty]=1;
q.push(make_pair(tx,ty));
}
}
}
return res;
}
int main(){
cin>>n>>m;
rep(i,1,n) rep(j,1,m)
cin>>g[i][j];
int cnt=0,s=0;
rep(i,1,n) rep(j,1,m)
if(!st[i][j]) s=max(s,bfs(i,j)),cnt++;
cout<<cnt<<endl<<s<<endl;
}

浙公网安备 33010602011771号