C++ 代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std ;
typedef pair<int,int> PII ;
const int N = 50 ;
int g[N][N] ;
int dist[N][N] ;
int dx[] = {0,-1,0,1}, dy[] = {-1,0,1,0} ;
int n,m ;
int bfs(int x,int y){
dist[x][y] = 0 ;
queue<PII> q ;
q.push({x,y}) ;
int cnt = 0 ;
while(q.size()){
PII ele = q.front() ;
q.pop() ;
cnt ++ ;
int x = ele.first, y = ele.second ;
for(int i=0;i<4;i++){
if(!(g[x][y]>>i&1)){
int a = x + dx[i],b = y + dy[i] ;
if(dist[a][b] == -1){
dist[a][b] = dist[x][y] + 1 ;
q.push({a,b}) ;
}
}
}
}
return cnt ;
}
int main(){
scanf("%d%d",&n,&m) ;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
scanf("%d",&g[i][j]) ;
}
}
int res = 0,maxv = 0 ;
memset(dist,-1,sizeof dist) ;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(dist[i][j] == -1){
res ++ ;
maxv = max(maxv,bfs(i,j)) ;
}
}
}
printf("%d\n",res) ;
printf("%d\n",maxv) ;
return 0 ;
}
tql,根本没有想到二进制的方法
房子最外围一定有墙 所以判断出界的那一步可以省掉 这是一个细节
%%%
能想到二进制,很牛皮
想问一下就是最开始初始化以后第一个点(0,0)必然会进bfs,但是如果0,0点是墙,周围也都是墙的话 ,按照代码他也会先进队列,然后 在pop之后让cnt=1返回 ,但是这样是并不会有房间应该为0啊,而且这样也会增加一个房间的个数
上面说错了不是cnt=1,是area=1;就是第一个点st肯定是0那就肯定会进bfs的,如果0,0这个点旁边都有墙那岂不是每次返回area=1,然后cnt也一直加 加加。这里搞不明白,有没有佬能教教
大佬,可以帮我看一下吗
你忘记判断q和t是否出界了
根据这道题题意 房子最外围一定有墙 是可以不需要判断q t是否出界的 但你需要把 if(!(g[x][y]>>i&1))放到前面
dist 代表什么?
这里的dist是判重的作用,dist初始化为-1,走过的点的dist值会一直增加,dist的最后一个值d[n][n]就是记录的面积,但是走到最后的二维坐标不知道,所以只有判重的作用可以用布尔数组替代
哦,谢谢!
大佬 为什么这道题目用dfs求连通块都是错的
能看一下嘛
dx[] = {0, -1, 0, 1} 吧
你的墙的顺序错了
https://www.acwing.com/activity/content/code/content/4062147/
最下面用你的代码AC了
你看一看吧
嗯嗯多谢大佬 我已经发现错误了
haode
那我用你AC的代码就先删了啊
好的 没问题😇
好想法啊,直接二进制来搜索
自己的想法好啦胯啊
那样设置方向数组的原因
https://www.acwing.com/activity/content/code/content/1838822/
https://www.acwing.com/solution/content/49350/
解释了为什么要用数组坐标
对于方向来说, 比如往西走, 那行要保持不变, 列要往左一格, 所以是{0, -1}; 而对于往东也是同理{行不变, 列加一)。 实际上跟我们认为的直角坐标还是有一点区别的。
为什么西边不是(-1, 0), 北边不是(0, 1), 南边不是(0, -1), 东边不是(1, 0)
数组坐标和正常的直角坐标系不太一样,这里是按数组坐标做的
知道了向下是x轴, 向右是y轴
是的
前边的解释都懂了,但是为什么是用数组的坐标来表示方向呢?题目里好像没有说明啊,是这种有图的题,都是默认按数组坐标做的么?
习惯这样做,方便二进制枚举
https://www.acwing.com/solution/content/49350/
请问这句话dist[a][b] = dist[x][y] + 1 ; 具体表示什么含义
如果改成dist[a][b]=1,也可以AC。
在这里没什么特殊含义,作用是判重
oh,好的~
其实是标记这个点被遍历过了 在这个代码里面应该改成dist[a][b]=0 但是因为未遍历的状态是-1 所以你改成任意不等于-1的数都可以ac
为什么我方向不按这个写按照
int xx[] = {-1,0,1,0};
int yy[] = {0,1,0,-1};
写答案就不对了求指点
这个问题我刚也碰到了,想明白了,因为我们把
2^0, 2^1, 2^2, 2^3
是按顺序排的,for(int i = 0; i < 4; i ++ )
。0
就对应的西方向,所以必须是int dx[4] = {0, -1, 0, 1}, dy[4] = {-1, 0, 1, 0};
a,b,是通过当前位置,加上偏移量得到下一个位置的坐标,然后判断合不合法,有没有越界
g[t.x][t.y]那里的移位操作是直接从当前位置的二进制位,来判断下个位置有没有墙
这两个操作的顺序得一致,所以那个偏移量不能随便换
我自己的理解。。不知道对不对可以参考一下
https://www.acwing.com/solution/content/49350/
厉害啊,大佬真心厉害,想不到哇