题意:给你一个n*m的地图,然后地图的每一个格子给你一个数,这个数用二进制表示哪一方有墙哪一方没有墙:如果按照北东南西的方向如果是1就有墙。
假如给你数为1,那么转化为2进制为0001,按照北东南西的方向只有第四个为1,那么就说明这个格子的西边是墙,其他三面就不是墙。
如果给的是15,那么转化为2进制就是1111,那么这个格子的四周都是墙。所以每个格子的最大值是15,最小值为0.
然后让你按照从大到小的顺序输出房间所占的格子数量(房间的定义是里面的任意两点可以互通)。
思路:
可以建立一个结构体,里面包含四个属性n,e,s,w分别代表了四个方向。如果为1就代表这个方向有墙。然后每次输入的时候可以不断除以2然后来给墙的值附1,然后就是一个dfs找联通块的数量和所占格子,最后排序一下就可以了。
#include<cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include<vector>
#include<queue>
#include<map>
#define sc_int(x) scanf("%d", &x)
#define sc_ll(x) scanf("%lld", &x)
#define pr_ll(x) printf("%lld", x)
#define pr_ll_n(x) printf("%lld\n", x)
#define pr_int_n(x) printf("%d\n", x)
#define ll long long
using namespace std;
const int N=1000000+100;
int n ,m,h,res=0;
int cnt[1010][1010];
bool st[1010][1010];
int sk[N];
struct lk{
int n;//北
int e;//东
int s;//南
int w;//西
}s[1100][1100];
void change(int x,int y )
{
int res=cnt[x][y];
if(res&1)s[x][y].w=1;//西
else s[x][y].w=0;
res>>=1;
if(res&1)s[x][y].s=1;
else s[x][y].s=0;
res>>=1;
if(res&1)s[x][y].e=1;
else s[x][y].e=0;
res>>=1;
if(res&1)s[x][y].n=1;
else s[x][y].n=0;
//cout<<s[x][y].n<<s[x][y].e<<s[x][y].w<<s[x][y].s<<endl;
}
int dx[5]={0,1,0,-1,0};
int dy[5]={0,0,1,0,-1};
void dfs(int x,int y )
{
res++;
if(!st[x+1][y]&&!s[x][y].s&&!s[x+1][y].n&&x+1<=n){
st[x+1][y]=1;
//cout<<"?\n";
dfs(x+1,y);
}
if(!st[x-1][y]&&!s[x][y].n&&!s[x-1][y].s&&x-1>=1){
st[x-1][y]=1;
dfs(x-1,y);
}
if(!st[x][y-1]&&!s[x][y].w&&!s[x][y-1].e&&y-1>=1){
st[x][y-1]=1;
dfs(x,y-1);
}
if(!st[x][y+1]&&!s[x][y].e&&!s[x][y+1].w&&y+1<=m){
st[x][y+1]=1;
dfs(x,y+1);
}
}
int main()
{
int t;
cin>>n>>m;
for(int i =1;i<=n;i++)
{
for(int j =1;j<=m;j++){
cin>>cnt[i][j];
change(i,j);
}
}
int tim=0;
for(int i =1;i<=n;i++)
{
for(int j =1;j<=m;j++)
{
if(!st[i][j]){
st[i][j]=1;
dfs(i,j);
sk[++tim]=res;
//cout<<res<<endl;
res=0;
}
}
}
sort(sk+1,sk+1+tim);
for(int i =tim;i>=1;i--)
cout<<sk[i]<<" ";
return 0;
}