1002: 当不成勇者的Water只好去下棋了
Time Limit: 1 Sec Memory Limit: 128 MBDescription
由于魔王BOSS躲起来了,说好要当勇者的Water只好去下棋了,他很厉害,基本每局必输。
Water总是不知道为什么把自己的棋下得东一块西一块,而块与块之间总是被对手的棋隔开。概率统计挂了的Water一直没搞清楚到底自己被别人分成了多少块,又来找你帮忙。
假定Water的棋为X,对手的棋为O。
给出一个矩阵棋盘,上面布满了棋子,求Water的棋子究竟被对手分成了多少块?
(为了和谐,我们还是用0011代表OOXX)
Input
第一行为n, m。 (0 < n,m <= 100)
接下来 n 行 m 列为01矩阵。
1 为Water的棋。
Output
每组数据输出一行,表示块数。
Sample Input
2 2
01
10
2 3
101
011
Sample Output
2
2
这道题利用的原理是图的填色,从一个二维数组第一个元素开始进行遍历,如果发现一个元素a是有效的,那么久在他的周围找同样有效的元素b,如果找到了,那么就在元素b的周围继续寻找。很明显,这可以用递归来实现。当然你也可以用栈来模拟递归实现。
下面来看看伪代码:
1 4 6 2 010200 3 111030 4 110030 5 100033 6 7 /* Floodfill */ 8 bool validNode(newnode) { 9 cond1 = inMatrix();//是否在图内部 10 cond2 = isFreeNode();//是否是有效元素(这里指值为1)&&是否已经是某个块的成员 11 return cond1 && cond2; 12 } 13 14 void floodfill(node) { 15 if node是有效元素 { 16 if node还不是某块的成员 17 c[node.x][node.y] = color; 18 19 //遍历上下左右四个元素 20 for (direction dir) { 21 newnode = extend(node, dir); 22 if (validNode(newnode)) 23 floodfill(newnode); 24 } 25 } 26 } 27 28 char g[n][m];//储存元素的数组 29 30 int color = 0;//分块的标志 31 32 int c[n][m];//分块记录 33 34 init();//初始化 35 36 readGraph();//读取分块记录 37 38 //遍历全部元素,进行分块 39 for (i = 0...n) 40 for (j = 0...m) { 41 // c[i][j] == 0 && g[i][j] == '1' 42 node = freeNode(); 43 color++; 44 floodfill(node); 45 }
然后递归的代码实现如下:
1 #include <iostream> 2 #include <stdio.h> 3 #include <set> 4 5 using namespace std; 6 7 struct Node{ 8 int x; 9 int y; 10 Node(int x_ = 0, int y_ = 0) { 11 x = x_; 12 y = y_; 13 } 14 }; 15 16 //上下左右四个节点 17 int borderUponX[4] = {0, 0, 1, -1}; 18 int borderUponY[4] = {1, -1, 0, 0}; 19 int n, m; 20 char g[101][101]; 21 int color = 0; 22 int c[101][101]; 23 24 bool validNode(Node newnode) { 25 if (newnode.x < 0 || newnode.x > n || newnode.y < 0 || newnode.y > m) 26 return false; 27 if (g[newnode.x][newnode.y] != '1' || c[newnode.x][newnode.y] != -1) 28 return false; 29 return true; 30 } 31 32 void floodfill(Node node) { 33 if(g[node.x][node.y] == '1') { 34 if (c[node.x][node.y] == -1) 35 c[node.x][node.y] = color; 36 37 for (int i = 0; i != 4; i++) { 38 int pathX = node.x + borderUponX[i]; 39 int pathY = node.y + borderUponY[i]; 40 Node t = Node(pathX, pathY); 41 if (validNode(t)) { 42 floodfill(t); 43 } 44 } 45 } 46 } 47 48 void init() { 49 for (int i = 0; i != n; i++) { 50 scanf("%s", g[i]); 51 } 52 for (int i = 0; i != n; i++) 53 for (int j = 0; j != m; j++) 54 c[i][j] = -1; 55 } 56 57 void readGraph() { 58 set<int> count; 59 for (int i = 0; i != n; i++) { 60 for (int j = 0;j != m; j++) { 61 if (c[i][j] != -1 && g[i][j] != '0') { 62 count.insert(c[i][j]); 63 } 64 } 65 } 66 printf("%d ", count.size()); 67 } 68 69 int main() { 70 while (scanf("%d%d", &n, &m) != EOF) { 71 init(); 72 73 for (int i = 0; i != n; i++) { 74 for (int j = 0;j != m; j++) { 75 color++; 76 floodfill(Node(i, j)); 77 } 78 } 79 readGraph(); 80 } 81 82 return 0; 83 }