【HDU 1198】Farm Irrigation(dfs+并查集+bfs)

来源:互联网 发布:毛衣编制软件 编辑:程序博客网 时间:2024/05/19 20:38

Description

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

题目大意

给你11种类型的water pipes,每一种pipes中都有不同流向的河流,现在给以一个由这些类型的water pipes拼接成的一个N*M的农田,对于相同流向的河流可以相连,比如A的上方可以连接E等等于A向上走河流方向相同的pipes,B的右方可以连接F,C等等于B向右走河流方向相同的pipes。对于每一个联通块(对于有河流连接的N个块其联通块数为1,对于单独的一个无任何连接的块其联通块数也为1)需要一个水源,现在问你组成的这N*M的农田至少需要几个水源。
比如Figure 2图中总共有3个联通块数,所以需要3个水源。

思路

这题实现的方法非常多,可以用并查集,dfs和bfs,因为我是在搜索专题遇见的这题所以用dfs写的,对于判断一个块是否可以和另一个块相连时,需要考虑河流的流向与搜索的方向,比如我向上搜索,那么我这个块中如果有向上流的河流(河流的水源都是在块的中间,比如A块河流有两个流向,一个向上,一个向左),那么就可以判断有无与它可以相连的块,如果这个块中没有向上流的河流那么这个搜索方向必定没有可以与它相连的块。对于判断是否可以相连只需要将河流流向可以相连的块全部找出来,若果搜素走的下一个块在这些块当中表示可以相连。
然而这题有11种类型的pipes,我可能太渣了,所以用最原始的办法写的判断是否可以相连的函数,足足有100多行。终究还是自己太垃圾了。
大神代码见(并查集,dfs双实现): HDU 1198 Farm Irrigation (并查集 和 dfs两种实现)

代码

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <queue>using namespace std;const int maxn=250+5;int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};int vis[maxn][maxn],map[maxn][maxn],n,m;bool iss(int x,int y,int i)//i表示当前搜索的方向,0:down 1:right 2:up 3:left{    //A    if(x==0&&i==2)//当前块为A块向x值减小方向搜索即向上(up)。     {        if(y==2||y==3||y==4||y==7||y==8||y==9||y==10) return true;//向上搜索可以和A块相连的块         else return false;//找不到返回false     }    else if(x==0&&i==3)//当前块为A块向y值减小方向搜索即向左(left)。    {        if(y==1||y==3||y==5||y==6||y==8||y==9||y==10) return true;//向左搜索可以和A块相连的块         else return false;//找不到返回false     }    //B    if(x==1&&i==2)    {        if(y==2||y==3||y==4||y==7||y==8||y==9||y==10) return true;        else return false;    }    else if(x==1&&i==1)    {        if(y==0||y==2||y==5||y==6||y==7||y==8||y==10) return true;        else return false;    }    //C    if(x==2&&i==3)    {        if(y==1||y==3||y==5||y==6||y==8||y==9||y==10) return true;        else return false;    }    else if(x==2&&i==0)    {        if(y==0||y==1||y==4||y==6||y==7||y==9||y==10) return true;        else return false;    }    //D    if(x==3&&i==1)    {        if(y==0||y==2||y==5||y==6||y==7||y==8||y==10) return true;        else return false;      }    else if(x==3&&i==0)    {        if(y==0||y==1||y==4||y==6||y==7||y==9||y==10) return true;        else return false;    }    //E    if(x==4&&i==2)    {        if(y==2||y==3||y==4||y==7||y==8||y==9||y==10) return true;        else return false;    }    else if(x==4&&i==0)    {        if(y==0||y==1||y==4||y==6||y==7||y==9||y==10) return true;        else return false;    }    //F    if(x==5&&i==3)    {        if(y==1||y==3||y==5||y==6||y==8||y==9||y==10) return true;        else return false;    }    else if(x==5&&i==1)    {        if(y==0||y==2||y==5||y==6||y==7||y==8||y==10) return true;        else return false;      }    //G    //0:down 1:right 2:up 3:left    if(x==6&&i==3)    {        if(y==1||y==3||y==5||y==6||y==8||y==9||y==10) return 1;        else return 0;    }    else if(x==6&&i==2)    {        if(y==2||y==3||y==4||y==7||y==8||y==9||y==10) return 1;        else return 0;    }    else if(x==6&&i==1)    {        if(y==0||y==2||y==5||y==6||y==7||y==8||y==10) return 1;        else return 0;    }    //H    if(x==7&&i==3)    {        if(y==1||y==3||y==5||y==6||y==8||y==9||y==10) return 1;        else return 0;    }    else if(x==7&&i==2)    {        if(y==2||y==3||y==4||y==7||y==8||y==9||y==10) return 1;        else return 0;    }    else if(x==7&&i==0)    {        if(y==0||y==1||y==4||y==6||y==7||y==9||y==10) return 1;        else return 0;    }    //I    if(x==8&&i==3)    {        if(y==1||y==3||y==5||y==6||y==8||y==9||y==10) return 1;        else return 0;    }    else if(x==8&&i==1)    {        if(y==0||y==2||y==5||y==6||y==7||y==8||y==10) return 1;        else return 0;    }    else if(x==8&&i==0)    {        if(y==0||y==1||y==4||y==6||y==7||y==9||y==10) return 1;        else return 0;    }    //J    if(x==9&&i==2)    {        if(y==2||y==3||y==4||y==7||y==8||y==9||y==10) return 1;        else return 0;    }    else if(x==9&&i==1)    {        if(y==0||y==2||y==5||y==6||y==7||y==8||y==10) return 1;        else return 0;    }    else if(x==9&&i==0)    {        if(y==0||y==1||y==4||y==6||y==7||y==9||y==10) return 1;        else return 0;    }    //K    if(x==10&&i==0)    {        if(y==0||y==1||y==4||y==6||y==7||y==9||y==10) return 1;        else return 0;    }    else if(x==10&&i==1)    {        if(y==0||y==2||y==5||y==6||y==7||y==8||y==10) return 1;        else return 0;    }    else if(x==10&&i==2)    {        if(y==2||y==3||y==4||y==7||y==8||y==9||y==10) return 1;        else return 0;    }    else if(x==10&&i==3)    {        if(y==1||y==3||y==5||y==6||y==8||y==9||y==10) return 1;        else return 0;    }    return false;//向河流流向方向之外的方向搜索必定没有可以相连的块,直接返回false }void dfs(int x,int y)//dfs寻找联通块 {    if(vis[x][y]) return;    vis[x][y]=1;    for(int i=0;i<4;i++)    {        int desx=x+dir[i][0];        int desy=y+dir[i][1];        //int tmp=iss(map[x][y],map[desx][desy],i);        //cout<<"tmp:"<<tmp<<endl;        if(iss(map[x][y],map[desx][desy],i)&&desx>=0&&desx<n&&desy>=0&&desy<m)        {            dfs(desx,desy);        }    }}int main(){    while(scanf("%d %d",&n,&m))    {        memset(vis,0,sizeof(vis));        if(n==-1&&m==-1) break;        string s;        for(int i=0;i<n;i++)        {            cin>>s;            for(int j=0;j<m;j++)            {                map[i][j]=s[j]-'A';//从0~10标记11种类型的块             }        }        int cnt=0;        for(int i=0;i<n;i++)        {            for(int j=0;j<m;j++)            {                //从当前块出发,dfs与它可以相连的所有块,并标记这些块的vis为1,则一个联通块cnt+1;                 if(vis[i][j]) continue;                ++cnt;                dfs(i,j);            }        }        printf("%d\n",cnt);    }    return 0;}
0 0