POJ 2386 (深搜或广搜)

Lake Counting
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 17917 Accepted: 9069

Description

Due to recent rains, water has pooled in various places in Farmer John's field, which is represented by a rectangle of N x M (1 <= N <= 100; 1 <= M <= 100) squares. Each square contains either water ('W') or dry land ('.'). Farmer John would like to figure out how many ponds have formed in his field. A pond is a connected set of squares with water in them, where a square is considered adjacent to all eight of its neighbors. 

Given a diagram of Farmer John's field, determine how many ponds he has.

Input

* Line 1: Two space-separated integers: N and M 

* Lines 2..N+1: M characters per line representing one row of Farmer John's field. Each character is either 'W' or '.'. The characters do not have spaces between them.

Output

* Line 1: The number of ponds in Farmer John's field.

Sample Input

10 12
W........WW.
.WWW.....WWW
....WW...WW.
.........WW.
.........W..
..W......W..
.W.W.....WW.
W.W.W.....W.
.W.W......W.
..W.......W.

Sample Output

3

这道题目比较基础,可以深搜也可以广搜

深搜快一点 36ms,广搜47ms。很好的练习题目。

把注释的去掉就是深搜了。

[cpp]   view plain  copy
  1. #include <stdio.h>  
  2. #include <queue>  
  3. using namespace std;  
  4. #define N 102  
  5.   
  6. char map[N][N];  
  7. int n,m;  
  8. struct Node  
  9. {  
  10.     int x,y;  
  11. };  
  12. int dis[10][3]={ {0,1},{0,-1},{-1,0},{1,0},{-1,-1},{-1,1},{1,-1},{1,1} };  
  13. void search(int a,int b)  
  14. {  
  15.     /*map[a][b]='.'; 
  16.     for(int i=0;i<8;i++) 
  17.     { 
  18.         int tmpx=a+dis[i][0]; 
  19.         int tmpy=b+dis[i][1]; 
  20.         if(tmpx>0 && tmpx<=n && tmpy>0 && tmpy<=m && map[tmpx][tmpy]=='W' ){ 
  21.             //map[tmpx][tmpy]='.'; 
  22.             search(tmpx,tmpy); 
  23.         } 
  24.     }*/  
  25.     Node tmp,be;  
  26.     be.x=a,be.y=b;  
  27.     queue<Node> v;  
  28.     v.push(be);  
  29.     map[a][b]='.';  
  30.     while(!v.empty())  
  31.     {  
  32.         be=v.front();  
  33.         v.pop();  
  34.         for(int i=0;i<8;i++)  
  35.         {  
  36.             tmp.x=be.x+dis[i][0];  
  37.             tmp.y=be.y+dis[i][1];  
  38.             if(tmp.x>0 && tmp.x<=n && tmp.y>0 && tmp.y<=m && map[tmp.x][tmp.y]=='W' )  
  39.             {  
  40.                 v.push(tmp);  
  41.                 map[tmp.x][tmp.y]='.';  
  42.             }  
  43.         }  
  44.     }  
  45. }  
  46.   
  47. int main()  
  48. {  
  49.     int i,j,count;  
  50.     while(~scanf("%d %d",&n,&m))  
  51.     {  
  52.         getchar();  
  53.         count=0;  
  54.         for(i=1;i<=n;i++){  
  55.             for(j=1;j<=m;j++){  
  56.                 scanf("%c",&map[i][j]);}  ///缺了括号,害死人啊  
  57.             getchar();}  
  58.         for(i=1;i<=n;i++)  
  59.             for(j=1;j<=m;j++)  
  60.                 if(map[i][j]=='W')  
  61.                 {  
  62.                     //printf("%d %d\n",i,j);  
  63.                     search(i,j);count++;  
  64.                 }  
  65.         printf("%d\n",count);  
  66.     }  
  67.     return 0;  
  68. }  
[cpp]   view plain  copy
[cpp]   view plain  c
[cpp]   view plain  cop
[cpp]   view plain  copy
[cpp]   view plain  copy
  1. #include <stdio.h>  
  2. #include <queue>  
  3. using namespace std;  
  4. #define N 102  
  5.   
  6. char map[N][N];  
  7. int n,m;  
  8.   
  9. void search(int i,int j)  
  10. {  
  11.     if(map[i][j-1]=='W') { map[i][j-1]='.'; search(i,j-1); }  
  12.     if(map[i][j+1]=='W') { map[i][j+1]='.'; search(i,j+1); }  
  13.     if(map[i-1][j]=='W') { map[i-1][j]='.'; search(i-1,j); }  
  14.     if(map[i+1][j]=='W') { map[i+1][j]='.'; search(i+1,j); }  
  15.     if(map[i-1][j-1]=='W') { map[i-1][j-1]='.'; search(i-1,j-1); }  
  16.     if(map[i-1][j+1]=='W') { map[i-1][j+1]='.'; search(i-1,j+1); }  
  17.     if(map[i+1][j-1]=='W') { map[i+1][j-1]='.'; search(i+1,j-1); }  
  18.     if(map[i+1][j+1]=='W') { map[i+1][j+1]='.'; search(i+1,j+1); }  
  19. }  
  20.   
  21. int main()  
  22. {  
  23.     int i,j,count;  
  24.     while(~scanf("%d %d",&n,&m))  
  25.     {  
  26.         getchar();  
  27.         count=0;  
  28.         for(i=1;i<=n;i++){  
  29.             for(j=1;j<=m;j++){  
  30.                 scanf("%c",&map[i][j]);}  ///缺了括号,害死人啊  
  31.             getchar();}  
  32.         for(i=1;i<=n;i++)  
  33.             for(j=1;j<=m;j++)  
  34.                 if(map[i][j]=='W')  
  35.                 {  
  36.                     //printf("%d %d\n",i,j);  
  37.                     search(i,j);count++;  
  38.                 }  
  39.         printf("%d\n",count);  
  40.     }  
  41.     return 0;  
  42. }
  43. 题意:有一个大小为N×M的园子,雨后积起了水。八连通的积水被认为是连在一起的。求园子里一共有多少水洼?

    * * *

    * W*    (八连通指的就是左图中相对W的*的部分)

    * * *

    Sample Input

    10 12
    W........WW.
    .WWW.....WWW
    ....WW...WW.
    .........WW.
    .........W..
    ..W......W..
    .W.W.....WW.
    W.W.W.....W.
    .W.W......W.
    ..W.......W.

    Sample Output

    3
    PS:样例中的3个水洼分别是在左上,左下,和右方。
    这是的一道入门的深度优先搜索题,很简单~~
    从任意的W开始,不停地把邻接的部分(八连通)用'.'代替。1次DFS后与初始的这个W连接的所有W就都被替换成了'.',因此直到图中不在存在W为止,总共进行DFS的次数就是答案了。8个方向的共对应了8种状态转移,每个格子作为DFS的参数至多被调用一次,所以复杂度为O(8×M×N)=O(M×N)。
    
    复制代码
    #include<iostream>
    #include<algorithm>
    using namespace std;
    char field[105][105];
    int N,M;
    void dfs(int x, int y)
    {
        //现在的位置(x,y)
        field[x][y] = '.';//将现在所在位置替换为'.'
        for (int dx = -1; dx <= 1; dx++)//循环遍历连通的8个方向
        {
            for (int dy = -1; dy <= 1; dy++)
            {
                int nx = x + dx, ny = y + dy;//向x方向移动dx,向y方向移动dy,移动的结果为(nx,ny)
                if (0 <= nx&&nx <= N && 0 <= ny&&ny <= M&&field[nx][ny] == 'W')//判断(nx,ny)是不是在园子里,以及是否有积水
                    dfs(nx, ny);
            }
        }
    }
    int main()
    {
        cin >> N >> M;
        for (int i = 0; i < N; i++)
            for (int j = 0; j < M; j++)
                cin >> field[i][j];
        int res = 0;
        for(int i=0;i<N;i++)
            for(int j=0;j<M;j++)
                if (field[i][j] == 'W')//从有积水的地方开始dfs
                {
                    dfs(i, j);
                    res++;
                }
        cout << res << endl;
        return 0;
    }

    2道题目都差不多,就是问和相邻所有点都有相同数据相连的作为一个联通快,问有多少个连通块

     

    因为最近对搜索题目很是畏惧,总是需要看别人代码才能上手,就先拿这两道简单的dfs题目来练练手,顺便理一理dfs的思路,分析清楚dfs的退出递归的条件和什么时候进行递归调用是至关重要的,这两道题目不涉及回溯,对于需要回溯的题目也要清楚分析,找到回溯条件,在对一个新的状态dfs时,后面加上回溯的语句

     

    HDU1241代码:

    复制代码
     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 using namespace std;
     5 
     6 int n,m,ans;
     7 int visit[102][102],dir[8][2] = {{1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}};
     8 char mat[102][102];
     9 
    10 void dfs(int a,int b)
    11 {
    12     visit[a][b] = 1;
    13     for(int i=0;i<8;i++){
    14         int xx = a+dir[i][0];
    15         int yy = b+dir[i][1];
    16         if(xx>=0&&xx<n&&yy>=0&&yy<m&&mat[xx][yy]=='@'){
    17             if(!visit[xx][yy])
    18                 dfs(xx,yy);
    19         }
    20     }
    21 }
    22 int main()
    23 {
    24     while(~scanf("%d%d",&n,&m)){
    25         if(n==0&&m==0) break;
    26 
    27         for(int i=0;i<n;i++){
    28             for(int j=0;j<m;j++)
    29                 cin>>mat[i][j];
    30         }
    31 
    32         memset(visit,0,sizeof(visit));
    33         ans = 0;
    34 
    35         for(int i=0;i<n;i++)
    36         {
    37             for(int j=0;j<m;j++)
    38                 if(!visit[i][j]&&mat[i][j] == '@')
    39                 {
    40                     dfs(i,j);
    41                     ans++;
    42                 }
    43         }
    44 
    45         printf("%d\n",ans);
    46     }
    47     return 0;
    48 }
    复制代码

     

    POJ2386代码:

    复制代码
     1 #include <cstdio>
     2 #include <cstring>
     3 
     4 using namespace std;
     5 
     6 #define N 102
     7 
     8 int n,m,ans;
     9 int visit[N][N],dir[8][2] = {{1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}};
    10 char mat[N][N];
    11 
    12 void dfs(int x,int y)
    13 {
    14     visit[x][y]=1;
    15     for(int i=0;i<8;i++){
    16         int xx=x+dir[i][0];
    17         int yy=y+dir[i][1];
    18         if(xx>=0&&x<n&&yy>=0&&yy<m&&mat[xx][yy]=='W'&&!visit[xx][yy])
    19             dfs(xx,yy);
    20     }
    21 }
    22 
    23 int main()
    24 {
    25     while(~scanf("%d%d",&n,&m)){
    26         for(int i=0;i<n;i++)
    27             scanf("%s",mat[i]);
    28 
    29         memset(visit,0,sizeof(visit));
    30         ans=0;
    31 
    32         for(int i = 0 ;i<n;i++)
    33         for(int j=0;j<m;j++){
    34             if(mat[i][j] == 'W'&&!visit[i][j])
    35             {
    36                 dfs(i,j);
    37                 ans++;
    38             }
    39         }
    40 
    41         printf("%d\n",ans);
    42     }
    43     return 0;
    44 }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值