ZOJ 2412 Farm Irrigation

  

Farm Irrigation


Time Limit: 2 Seconds      Memory Limit: 65536 KB


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

分析:

  该题目的大致意思就是,给定你一个农田的矩阵,矩阵中每个元素都有一种类型的水管,问最少配置几个水源可以灌溉整个农田?很显然,这是一个图的遍历问题。每个元素做为一个节点,水管的方向代表从当前这个节点可以到达的方向(同时要保证相邻的节点也有对应的水管进行连接)。所以,这里的主要问题就是:当处于农田某个位置时,如何判断他的四个方向是否可以走?可以得话,直接递归调用遍历函数dfs()访问下个一元素即可,这里便是dfs思想的体现。我一开始想到的办法是,判断当前的字母是什么,比如说是A,然后再判断四个方向是否可以走:因为A的下和右没有水管指向,所以这两个方向肯定不可以走,然后判断左边是否是B或者C或者F或者G或者I或者J或者K(因为这几个字母都有指向左边的水管),有则可以从这个方向进行DFS。A的上方向同样处理。这样做下来之后,可以发现十分的不方便,要处理情况太多,代码量也将变得十分复杂(出现了很多的重复代码,几乎相当于用代码穷举出每个字母的每个方向是否可以走)。

  后来想到了一个比较巧妙的方法,其做法如下:

  声明一个如下的结构体

struct node
{
    char ch;//该位置的字母
    int flag;//用于判断该位置 是否遍历过
    int a,b,c,d;//分别表示左、上、右、下是否有水管。0表示没有,1表示有
};
node src[55][55];

  那么如何快速判断当前位置(x,y)的下一个方向(xx,yy)是否可达呢(假设(xx,yy)未访问过且没有越界)?前面已经说过,(x,y)可以向左边走的条件是左边那小块农田有个指向右边的水管,所以,我们只要判断(x,y)的各方向是否可以走,可以这样判断:

  假设(xx,yy)为(x,y)的上边相邻元素:若(x,y).b*(xx,yy).d==1,则可从(x,y)往上走

  假设(xx,yy)为(x,y)的下边相邻元素:若(x,y).d*(xx,yy).b==1,则可从(x,y)往下走

  假设(xx,yy)为(x,y)的左边相邻元素:若(x,y).a*(xx,yy).c==1,则可从(x,y)往左走

   假设(xx,yy)为(x,y)的右边相邻元素:若(x,y).c*(xx,yy).a==1,则可从(x,y)往右走

  所以,dfs(int x,int y)的函数实现如下:

void dfs (int x,int y)
{
    if(x<0||x>=m||y<0||y>=n) return ;//判断越界
    src[x][y].flag=1;
    if(x-1>=0&&src[x-1][y].flag==0&&src[x][y].b*src[x-1][y].d==1){//越界判断+访问标志判断+是否可走判断
        dfs(x-1,y);
    }
    if(x+1<m&&src[x+1][y].flag==0&&src[x][y].d*src[x+1][y].b==1){
        dfs(x+1,y);
    }
    if(y-1>=0&&src[x][y-1].flag==0&&src[x][y].a*src[x][y-1].c==1){
        dfs(x,y-1);
    }
    if(y+1<n&&src[x][y+1].flag==0&&src[x][y].c*src[x][y+1].a==1){
        dfs(x,y+1);
    }
    return ;
}

  具备以上的了解,则求其最小连通度即可。

  该题目的完整C++实现代码如下:

  1 #include <iostream>
  2 using namespace std;
  3 int m,n;
  4 struct node
  5 {
  6     char ch;
  7     int flag;
  8     int a,b,c,d;//分别表示左、上、右、下
  9 };
 10
 11 node src[55][55];
 12
 13
 14 void dfs (int x,int y)
 15 {
 16     if(x<0||x>=m||y<0||y>=n) return ;
 17     src[x][y].flag=1;
 18     if(x-1>=0&&src[x-1][y].flag==0&&src[x][y].b*src[x-1][y].d==1){
 19         dfs(x-1,y);
 20     }
 21     if(x+1<m&&src[x+1][y].flag==0&&src[x][y].d*src[x+1][y].b==1){
 22         dfs(x+1,y);
 23     }
 24     if(y-1>=0&&src[x][y-1].flag==0&&src[x][y].a*src[x][y-1].c==1){
 25         dfs(x,y-1);
 26     }
 27     if(y+1<n&&src[x][y+1].flag==0&&src[x][y].c*src[x][y+1].a==1){
 28         dfs(x,y+1);
 29     }
 30     return ;
 31 }
 32
 33 int main()
 34 {
 35     while(cin>>m>>n){
 36         if(m<0||n<0) break;
 37         for(int i=0;i<m;i++){
 38             for(int j=0;j<n;j++){
 39                 cin>>src[i][j].ch;
 40                 switch(src[i][j].ch){
 41                     case ‘A‘:
 42                         src[i][j].a=1;
 43                         src[i][j].b=1;
 44                         src[i][j].c=0;
 45                         src[i][j].d=0;
 46                         break;
 47                     case ‘B‘:
 48                         src[i][j].a=0;
 49                         src[i][j].b=1;
 50                         src[i][j].c=1;
 51                         src[i][j].d=0;
 52                         break;
 53                     case ‘C‘:
 54                         src[i][j].a=1;
 55                         src[i][j].b=0;
 56                         src[i][j].c=0;
 57                         src[i][j].d=1;
 58                         break;
 59                     case ‘D‘:
 60                         src[i][j].a=0;
 61                         src[i][j].b=0;
 62                         src[i][j].c=1;
 63                         src[i][j].d=1;
 64                         break;
 65                     case ‘E‘:
 66                         src[i][j].a=0;
 67                         src[i][j].b=1;
 68                         src[i][j].c=0;
 69                         src[i][j].d=1;
 70                         break;
 71                     case ‘F‘:
 72                         src[i][j].a=1;
 73                         src[i][j].b=0;
 74                         src[i][j].c=1;
 75                         src[i][j].d=0;
 76                         break;
 77                     case ‘G‘:
 78                         src[i][j].a=1;
 79                         src[i][j].b=1;
 80                         src[i][j].c=1;
 81                         src[i][j].d=0;
 82                         break;
 83                     case ‘H‘:
 84                         src[i][j].a=1;
 85                         src[i][j].b=1;
 86                         src[i][j].c=0;
 87                         src[i][j].d=1;
 88                         break;
 89                     case ‘I‘:
 90                         src[i][j].a=1;
 91                         src[i][j].b=0;
 92                         src[i][j].c=1;
 93                         src[i][j].d=1;
 94                         break;
 95                     case ‘J‘:
 96                         src[i][j].a=0;
 97                         src[i][j].b=1;
 98                         src[i][j].c=1;
 99                         src[i][j].d=1;
100                         break;
101                     case ‘K‘:
102                         src[i][j].a=1;
103                         src[i][j].b=1;
104                         src[i][j].c=1;
105                         src[i][j].d=1;
106                         break;
107                 }
108                 src[i][j].flag=0;
109             }
110         }
111         int ans=0;
112         for(int i=0;i<m;i++){
113             for(int j=0;j<n;j++){
114                 if(src[i][j].flag==0){
115                     ans++;
116                     dfs(i,j);
117                 }
118             }
119         }
120         cout<<ans<<endl;
121     }
122 }
时间: 2024-10-12 19:38:42

ZOJ 2412 Farm Irrigation的相关文章

ZOJ 2412 Farm Irrigation(DFS 条件连通块)

题意  两块农田里面的管道可以直接连接的话  他们就可以共用一个水源   有11种农田  上面的管道位置是一定的  给你一个农田矩阵  问至少需要多少水源 DFS的连通块问题  两个相邻农田的管道可以直接连接的话他们就属于一个连通块  题目就是求连通块个数 #include<cstdio> #include<cstring> using namespace std; const int N = 55; char mat[N][N]; int type[11][4] = { //对应

HDU 2412 Farm Irrigation

题目: 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 ma

Farm Irrigation

题目:Farm Irrigation 题目链接:http://210.34.193.66:8080/vj/Problem.jsp?pid=1494 题目思路:并查集 1 #include<stdio.h> 2 //并查集重点就是实现:查询某点在哪个集合.将两个集合合并 3 //查找点的祖先 4 int a[10000]; 5 int fun(int x) 6 { 7 int p=x; 8 // 初始化数组 a[i]=i; 9 // 也就是说当 a[i]==i 时,这是一个祖先,或者他是别人的子

HDU 1198 Farm Irrigation

Farm Irrigation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7897    Accepted Submission(s): 3418 Problem Description Benny has a spacious farm land to irrigate. The farm land is a rectangle

【简单并查集】Farm Irrigation

Farm Irrigation Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Total Submission(s) : 6   Accepted Submission(s) : 3 Font: Times New Roman | Verdana | Georgia Font Size: ← → Problem Description Benny has a spacious fa

hdu 1198 Farm Irrigation (搜索或并查集)

Farm Irrigation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5818    Accepted Submission(s): 2521 Problem Description Benny has a spacious farm land to irrigate. The farm land is a rectangle

Farm Irrigation HDU - 1198 (并查集)

Farm Irrigation HDU - 1198 题意:给11种管道,问草地最少需要打多少个井才可以全部灌溉. 把每种管道的状态用二进制表示一下,然后对每一块草地,判断能否和上面或者左面的草地的管道连接. 然后并查集搞一下. 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn=55; 4 5 int g[12]={10,9,6,5,12,3,11,14,7,13,15}; 6 int f[maxn*maxn]

HDU1198水管并查集Farm Irrigation

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

(hdu step 5.1.4)Farm Irrigation(在两个节点合并有限制条件的情况下,求集合的个数)

题目: Farm Irrigation Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 202 Accepted Submission(s): 104   Problem Description Benny has a spacious farm land to irrigate. The farm land is a rectangle,