J. Robot Factory

传送门

题意:给你一个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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值