HDU-1198 Farm Irrigation

题目:

Farm Irrigation
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 8823 Accepted Submission(s): 3817


Problem 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.

img 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

img 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

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include <iostream>
#include <queue>
#include <functional>
#include <vector>
#include <string>
#include <set>
#include <algorithm>

using namespace std;

int mx[]= {-1,1,0,0};
int my[]= {0,0,-1,1};

struct land
{
bool dire[4];
bool flag;
};

land L[550][550];

bool fill_dire[11][4]=
{
{1,0,1,0},
{
0,1,1,0
},
{
1,0,0,1
},
{
0,1,0,1
},
{
0,0,1,1
},
{
1,1,0,0
},
{
1,1,1,0
},
{
1,0,1,1
},
{
1,1,0,1
},
{
0,1,1,1
},
{
1,1,1,1
}
};

int M,N;

inline bool inrange(int x,int y)
{
if(x<0||x>=N||y<0||y>=M)
return false;
return true;
}

void fill_lands(int x,int y, int indir)
{
if(!inrange(x,y)||L[x][y].flag)
return;

switch(indir)
{
case -1:
break;
case 0:
if(!L[x][y].dire[1])
return;
break;
case 1:
if(!L[x][y].dire[0])
return;
break;
case 2:
if(!L[x][y].dire[3])
return;
break;
case 3:
if(!L[x][y].dire[2])
return;
break;
}

L[x][y].flag=true;

for(int i=0; i<4; ++i)
{
if(L[x][y].dire[i])
fill_lands(x+mx[i],y+my[i],i);
}
}

int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);

while(cin>>M>>N&&M!=-1)
{
for(int y=0; y<M; ++y)
{
string S;
cin>>S;
for(int x=0; x<N; ++x)
{
L[x][y].flag=false;
copy(fill_dire[S[x]-'A'],fill_dire[S[x]-'A']+4,L[x][y].dire);
}
}

int cnt=0;
for(int x=0; x<N; ++x)
{
for(int y=0; y<M; ++y)
{
if(!L[x][y].flag)
{
++cnt;
fill_lands(x,y,-1);
}
}
}

cout <<cnt<<endl;
}
return 0;
}

解析&吐槽:

跟正常的深搜差不多,就是增加了一个 bool 数组来表示哪里是联通的。每次递归的时候都在 4 个 方向里面选择联通的方向进行递归,递归的第三个参数表示之前的管道通过哪个方向到达这个管道, 在递归的开头判断如果这个地面有一个管道和之前的地面相连,就表示水可以从上一个地面流到这里, 就对此地面进行标记并继续递归,否则终止这条线路。

在主函数里面扫描每一个没有标记的位置并进行递归,然后自增计数器,最后计数器的值就是结果。

本作品采用 署名-相同方式共享 4.0 国际 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 “不科学的科学君” (Liu233w) 与博客链接: https://liu233w.github.io ,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系

加载评论框需要翻墙