[关闭]
@RiverHamster 2017-11-19T17:00:20.000000Z 字数 1778 阅读 10887

Luogu P1141 01迷宫(DFS联通块)

Luogu DFS 连通块


楼下都说这题是什么并查集什么的,其实DFS联通块就可以了,没有那么复杂,速度也快。
时间:216ms 单个点时间:68ms 空间:36MB
时间复杂度O(n^2)+O(m)

主要思路

很容易就可以发现,所有连接在一起的格子的答案是一样的
所以,只需要用DFS找到所有的联通块,联通块内所有的格子的答案都是这个联通块的格子数目。

程序实现

记录每个格子是否被搜过(在某个连通块中)。
两重循环,如果这格没搜过就从这个格子开始搜。
每搜到一个格子当前答案加1,数组记录当前格子位置,每次都向4个方向的满足条件的格子扩展。
搜完一块后把数组记录的格子的答案赋成连通块总的格子数。
读入时有个小技巧,对于二维字符数组a,scanf("%s",a[i]+1)可以以1下标读入一行。
(gets,strlen等同理,如strlen(s+1)1下标字符串长度)

关键代码

  1. for(int i=1;i<=n;i++)
  2. for(int j=1;j<=n;j++) if(!v[i][j]){ //枚举格子,没有访问过就DFS
  3. v[i][j]=true; //这格被访问
  4. now=0; //总数记为0
  5. dfs(i,j); //从这格开始搜索
  6. for(int i=1;i<=now;i++) f[ans[i][0]][ans[i][1]]=now; //依次赋值,重复使用并没有问题
  7. }
  1. #define nx x+dx[i] //增量数组表示下一个的x
  2. #define ny y+dy[i] //增量数组表示下一个的y
  3. #define check(x,y) (x>0&&x<=n&&y>0&&y<=n) //越界检查
  4. void dfs(int x,int y){
  5. now++; //记录答案
  6. ans[now][0]=x,ans[now][1]=y; //记录连通块的格子
  7. for(int i=0;i<4;i++){ //搜索下一格
  8. if(check(nx,ny)&&!v[nx][ny]&&a[x][y]!=a[nx][ny]){
  9. //越界、访问、颜色判断
  10. v[nx][ny]=true; //记录访问状态
  11. dfs(nx,ny); //下一格
  12. }
  13. }
  14. }

完整代码(快读+快输)

  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #define check(x,y) (x>0&&x<=n&&y>0&&y<=n)
  4. #define nx (x+dx[i])
  5. #define ny (y+dy[i])
  6. char a[1005][1005]; int f[1005][1005]; bool v[1005][1005];
  7. int n,m,dx[]={1,0,-1,0},dy[]={0,1,0,-1},now;
  8. int ans[1000005][2],Count; //变量定义防止太长压了行
  9. void dfs(int x,int y){
  10. now++;
  11. ans[now][0]=x,ans[now][1]=y;
  12. for(int i=0;i<4;i++){
  13. if(check(nx,ny)&&!v[nx][ny]&&a[x][y]!=a[nx][ny]){
  14. v[nx][ny]=true;
  15. dfs(nx,ny);
  16. }
  17. }
  18. }
  19. int res;
  20. char ch;
  21. inline int read(){
  22. res=0;
  23. while(isspace(ch=getchar()));
  24. do res=res*10+ch-'0'; while(isdigit(ch=getchar()));
  25. return res;
  26. }
  27. inline void write(int n){
  28. if(n==0) return;
  29. write(n/10);
  30. putchar(n%10+'0');
  31. }
  32. int main(){
  33. scanf("%d%d",&n,&m);
  34. for(int i=1;i<=n;i++) scanf("%s",a[i]+1);
  35. for(int i=1;i<=n;i++)
  36. for(int j=1;j<=n;j++) if(!v[i][j]){
  37. v[i][j]=true;now=0;
  38. dfs(i,j);
  39. for(int i=1;i<=now;i++) f[ans[i][0]][ans[i][1]]=now;
  40. }
  41. register int x,y;
  42. for(int i=1;i<=m;i++){
  43. x=read();y=read();
  44. write(f[x][y]);
  45. putchar('\n');
  46. }
  47. return 0;
  48. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注