1. 程式人生 > >Lake Counting(深度優先演算法)

Lake Counting(深度優先演算法)

這個題的模板 也可以AC 另兩個題 ,程式碼意思都是差不多的

Red and Black(找黑磚的個數)點選開啟連結

Oil Deposits(計算油田的個數)點選開啟連結

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

Hint

OUTPUT DETAILS:

There are three ponds: one in the upper left, one in the lower left,and one along the right side.

大致題意

有一個大小為N*M的園子,雨後積了很多水。八連通的積水被認為是在一起的。請求出園子裡共有多少個水窪?(八連通是指下圖中相對.的8 部分)

www

w.w

www

從任意的'W'開始,不停地把鄰接的部分用'.'代替,一次DFS(深度優先遍歷)遍歷後,與初始的這個 W 所連線的所有 'W' 都會被替換成 '.',因此直到圖中沒有 'W'為止,總共進行 DFS 的次數即為積水的次數。

程式碼如下:

第一種方法;

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
char a[1001][1001];
int n,m;
void DFS(int x,int y)
{
    int i,j,b,c;
    for(i=-1;i<=1;i++){
        for(j=-1;j<=1;j++){
            b=i+x;//代表了八個方向  (i-1,j-1)  (i-1,j)  (i-1,j+1) (i,j-1)
            c=y+j;//		  (i,j+1)   (i+1,j-1)  (i+1,j)  (i+1,j+1)
            if(b>=0&&b<n&&y>=0&&y<m&&a[b][c]=='W')
            {
                a[b][c]='.';//如果改點是 ’W' 的話 就另 該點是 '.' 以後也不訪問他
                DFS(b,c);// 去搜索該點
            }
        }
    }
}
int main()
{
    int i,j,flag=0;
    while(scanf("%d %d",&n,&m)!=EOF){
        memset(a,'0',sizeof(a));
        flag=0;
        for(i=0;i<=n-1;i++)
            scanf("%s",a[i]);
        for(i=0;i<=n-1;i++){
            for(j=0;j<=m-1;j++){
                if(a[i][j]=='W'){
                    flag++;//遇見一個水窪 就加加
                    DFS(i,j);//去搜索這一點的八個方向
                }
            }
        }
        printf("%d\n",flag);
    }
}

第二種方法:

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
char a[1001][1001];
int n,m;
void DFS(int i,int j)
{
    if(i>=0&&i<n&&j>=0&&j<m&&a[i][j]=='W'){
        a[i][j]='.';//相比於第一種,這裡用了八個 DFS,第一種用了迴圈來表示八個方向
        DFS(i-1,j-1);
        DFS(i-1,j);
        DFS(i-1,j+1);
        DFS(i,j-1);
        DFS(i,j+1);
        DFS(i+1,j-1);
        DFS(i+1,j);
        DFS(i+1,j+1);
    }
}
int main()
{
    int i,j,flag=0;
    while(scanf("%d %d",&n,&m)!=EOF){
        memset(a,'0',sizeof(a));
        flag=0;
        for(i=0;i<=n-1;i++)
            scanf("%s",a[i]);
        for(i=0;i<=n-1;i++){
            for(j=0;j<=m-1;j++){
                if(a[i][j]=='W'){
                    flag++;
                    DFS(i,j);
                }
            }
        }
        printf("%d\n",flag);
    }
}