题目描述
编程计算由"1"围成的下列图形的面积。面积计算方法是统计"1"所围成的闭合曲线中"0"点的数目。如图所示,在10*10的二维数组中,"1"围住了15个点,因此面积为15。
提示:queue
输入
测试次数t
每组测试数据格式为:
数组大小m,n
一个由0和1组成的m*n的二维数组
输出
对每个二维数组,输出符号"1"围住的"0"的个数,即围成的面积。假设一定有1组成的闭合曲线,但不唯一。
输入样例1
2
10 10
0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 1 0 0 0
0 0 0 0 1 0 0 1 0 0
0 0 0 0 0 1 0 0 1 0
0 0 1 0 0 0 1 0 1 0
0 1 0 1 0 1 0 0 1 0
0 1 0 0 1 1 0 1 1 0
0 0 1 0 0 0 0 1 0 0
0 0 0 1 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0
5 8
0 1 1 0 0 1 1 0
1 0 1 0 1 0 0 1
0 1 0 1 0 0 1 0
0 1 0 0 1 1 1 0
0 0 0 0 0 0 0 0
输出样例1
15
5
NOTICE:这道题题目读起来很好懂,算法的实现也很简单,难的是你要知道算法,我采用的算法也是借鉴csdn的大佬的;这题的思路是:将除了1围起来的0之外的所有0变成1,也就是除了面积部分之外其余全为1,这样子计算面积只需要遍历整个图数有多少个0就可以;具体实现的话,就是在原来的图的最外层加上一圈0,然后从最左上角的点开始,以类似走迷宫的方法走完围墙外的所有的0并将他们改为1,最后数多少个0得出结果;为什么要加一圈0呢:样例输入中的第二组测试数据给出答案,因为原来的图中围墙可能在最边上,这样子的话我们就不能够从左上角开始,将所有围墙外的点改为1,加一圈0的话,围墙外的任意两个点之间都可以到达。
#include <iostream>
using namespace std;
class Graph
{
private:
int** map;
int m, n;
public:
Graph()
{
cin >> m >> n;
map = new int* [m + 2];
for (int i = 0; i < m + 2; i++)
map[i] = new int[n + 2];
for (int i = 0; i < m + 2; i++)
for (int j = 0; j < n + 2; j++)
map[i][j] = 0;
for (int i = 1; i < m + 1; i++)
for (int j = 1; j < n + 1; j++)
cin >> map[i][j];
}
~Graph()
{
for (int i = 0; i < m + 2; i++)
delete[]map[i];
delete[]map;
}
void walk_map(int i, int j)
{
map[i][j] = 1;
if (j + 1 < n + 2 && map[i][j + 1] == 0)//j+1的判断一定要放前面!
walk_map(i, j + 1);
if (i + 1 < m + 2 && map[i + 1][j] == 0)
walk_map(i + 1, j);
if (j - 1 >= 0 && map[i][j - 1] == 0)
walk_map(i, j - 1);
if (i - 1 >= 0 && map[i - 1][j] == 0)
walk_map(i - 1, j);
}
void GetArea()
{
walk_map(0, 0);
int cnt = 0;
for (int i = 1; i < m + 1; i++)
for (int j = 1; j < n + 1; j++)
if (map[i][j] == 0)
cnt++;
cout << cnt << endl;
}
};
int main()
{
int t;
cin >> t;
while (t--)
{
Graph g;
g.GetArea();
}
return 0;
}