zoj 2412 Farm Irrigation ——DFS入门题

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1412

题意:

  有11种正方形,每种正方形里面对应一种形状的水管,不同的的正方形一用A到K表示,给一个矩阵,问至少需要多少个水源可以使矩形中所有的地方都可以被灌溉,如果两个相邻的正方形的水管正好对口,那么这两个正方形可以共用一个水源。

思路:

  开始感觉很复杂,明显可以DFS做,但是感觉比较麻烦,关键是怎么处理题目中的条件。

  首先,处理11种不同的水管,分4个方向,1表示有接口,0表示没有接口。用一个二维数组存所有种类的水管。

  然后,把输入的字符转化成数字,可以再输入的时候边输入边处理,用字符减去字符“A”就可以了,对应的上面给11中不同水管中的一种。以上这两个处理方法要注意,学习一下,稍微看了一下别人的代码才想到的。这种看似比较简单的处理,往往给解题带来比较大的方便。

  最后,就是如何深搜了。这个要考虑清楚。用一个flag二维数组表示是否访问过这个方格。深搜的时候,如果访问到它时,先判断它是否被访问过,然后立刻标记为已访问。然后就是判断当前方格的四个方向是不是有接口,如果某个方向有接口的话,就判断这个方向上的下一个方格中,和当前方格相邻的边是不是有接口,如果有接口,则继续深搜这个相邻的点。这里有个处理:(k+2)%4,意味着,比如:当前方格如果右边有接口,则判断右边的方格的左边的边是不是有接口,其它情况一样。然后就是主函数里面的dfs外面的for循环,思想和以前做过的zoj 1709是一样的,就是搜到某个点的时候,用一个mrk标记一下,把和它有关系的点都搜完,如果有符合条件的,mrk会改变,然后就cnt++用来计数,这种题目是相似的,都是要求符合条件的点相邻。

   有一个细节,就是矩阵的数组还是从1开始吧,数组稍微开大一点儿,这样在深搜下一个方向的时候,就不会因为数组越界出错了。这个问题以前没有注意到。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cctype>
 6 #include <stack>
 7 #include <queue>
 8 #include <cmath>
 9 #include <algorithm>
10 #define lson l, m, rt<<1
11 #define rson m+1, r, rt<<1|1
12 using namespace std;
13 typedef long long int LL;
14 const int MAXN =  0x3f3f3f3f;
15 const int  MIN =  -0x3f3f3f3f;
16 const double eps = 1e-9;
17 
18 int grid[11][4] = {{0,0,1,1},{1,0,0,1},{0,1,1,0},{1,1,0,0},{0,1,0,1},
19   {1,0,1,0},{1,0,1,1},{0,1,1,1},{1,1,1,0},{1,1,0,1},{1,1,1,1}};
20 int dir[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
21 bool flag[55][55];
22 int s[55][55];
23 bool mrk = false;
24 int n, m;
25 void dfs(int i, int j){
26   if (i <= 0 || i > m || j <= 0 || j > n) return;
27   if (flag[i][j]) return;
28   mrk = true; flag[i][j] = true;
29   for (int k = 0; k < 4; ++k){
30     if (grid[s[i][j]][k] && grid[s[i+dir[k][0]][j+dir[k][1]]][(k+2)%4]){
31       dfs(i+dir[k][0], j+dir[k][1]);
32     }
33   }
34   return;
35 }
36 int main(void){
37 #ifndef ONLINE_JUDGE
38   freopen("zoj2412.in", "r", stdin);
39 #endif
40   while (~scanf("%d%d", &m, &n)){
41     if (m+n<0) break; char ch; getchar(); int cnt = 0;
42     for (int i = 1; i <= m; ++i){
43       for (int j = 1; j <= n; ++j){
44         scanf("%c", &ch);
45         s[i][j] = ch-'A';
46       } getchar();
47     }
48     memset(flag, false, sizeof(flag));
49     for (int i = 1; i <= m; ++i){
50       for (int j = 1;j <= n; ++j){
51         mrk = false;
52         if (!flag[i][j]) dfs(i, j);
53         if (mrk) cnt++;
54       }
55     }
56     printf("%d\n", cnt);
57   }
58 
59   return 0;
60 }

竟然1A了……

posted on 2013-04-07 12:48  aries__liu  阅读(693)  评论(0编辑  收藏  举报