HDU1198 Farm Irrigation (DFS)

题目链接

Benny has a spacious farm land to irrigate. The farm land is a rectangle, and is divided into a lot of samll squares. Water pipes are placed in these squares. Different square has a different type of pipe. There are 11 types of pipes, which is marked from A to K, as Figure 1 shows. 

Figure 1



Benny has a map of his farm, which is an array of marks denoting the distribution of water pipes over the whole farm. For example, if he has a map 

ADC 
FJK 
IHE 

then the water pipes are distributed like 

Figure 2



Several wellsprings are found in the center of some squares, so water can flow along the pipes from one square to another. If water flow crosses one square, the whole farm land in this square is irrigated and will have a good harvest in autumn. 

Now Benny wants to know at least how many wellsprings should be found to have the whole farm land irrigated. Can you help him? 

Note: In the above example, at least 3 wellsprings are needed, as those red points in Figure 2 show. 

Input

There are several test cases! In each test case, the first line contains 2 integers M and N, then M lines follow. In each of these lines, there are N characters, in the range of 'A' to 'K', denoting the type of water pipe over the corresponding square. A negative M or N denotes the end of input, else you can assume 1 <= M, N <= 50. 

Output

For each test case, output in one line the least number of wellsprings needed. 

Sample Input

2 2
DK
HF

3 3
ADC
FJK
IHE

-1 -1

Sample Output

2
3

PS:这个题其实就是找图中有多少联通块,但是这个题比较麻烦的是,要去判断,当前管道是否可以和其他块管道形成联通块。判断联通块有并查集,DFS两种方法,这里介绍DFS,首先管道有四个方向可以导通,我们用四位二进制数表示,我们表示顺序为上左右下(比如A,1100)最后将4位二进制数最后化成10进制,后面判断的时候每次除以二,判断当前是否联通。注意:这里的顺序是上左下右,是每次判断的时候是要判断下一块和当前块是否能够连接,就是要判断下一块的方向是否和当前块的方向相反,比如A,B,A是左边可以走,判断B是右边可以走才可以联通。这样排序方向的好处是当前右移i为位,下一个板块右移(3-i)位判断联不联通就行了,细节看代码。

#include <iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<string>
#include<map>
#include<cmath>
#include<vector>
const int maxn=1e2+5;
const int mod=1e9+7;
const int inf=1e9;
#define me(a,b) memset(a,b,sizeof(a))
typedef long long ll;
using namespace std;
int ch[20]= {12,10,5,3,9,6,14,13,7,11,15};//各板块的联通的方向
int n,m,vis[maxn][maxn];
char maps[maxn][maxn];
int dx[4]={1,0,0,-1};//由于我们化为二进制的顺序为上左右下。
int dy[4]={0,1,-1,0};//所以这里的方向要和我们定义的方向要为下右左上。dx数组管上下,dy数组管左右
int check(int x,int y)//判断是否越界
{
    if(x<0||x>=n||y<0||y>=m||vis[x][y])
        return 0;
    return 1;
}
void dfs(int x,int y)
{
    int tu=ch[maps[x][y]-'A'];//获得当前可走方向
    for(int i=0; i<4; i++)
    {
        int x1=x+dx[i];
        int y1=y+dy[i];
        if(check(x1,y1))
        {
            int tv=ch[maps[x1][y1]-'A'];//获得下一步可走方向。
            if(((tu>>i)&1)&&((tv>>(3-i))&1))//前面判断当前方向是否可走,后面判断相反方向是否可走。
            {
                vis[x1][y1]=1;
                dfs(x1,y1);
            }
        }
    }
}
int main()
{
    while(scanf("%d%d",&n,&m)&&!(m==-1&&n==-1))
    {
        me(vis,0);
        int sum=0;
        for(int i=0; i<n; i++)
            scanf("%s",maps[i]);
        for(int i=0; i<n; i++)
            for(int j=0; j<m; j++)
                if(!vis[i][j])//之前没有走过的,都需要一个新水泵
                {
                    sum++;
                    vis[i][j]=1;
                    dfs(i,j);
                }
        printf("%d\n",sum);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41292370/article/details/84565320