【提高】卫星照片
题目描述
农夫约翰总是想要一个农场的地图,所以他拍摄了一张N行M列的卫星照片。一部分的照片看起来像这样:
..................
..#####.......##..
..#####......##...
..................
#.......###.....#.
#.....#####.......
他认为每个联通块都是一个谷仓或一头奶牛。联通块由若干个彼此水平或垂直相邻的#符号组成。以下的照片被认为是两个联通块:
....
.#..
..#.
....
农夫约翰认为一个联通块是谷仓,当且仅当它是一个完整的矩形,否则该联通块是一头奶牛。在第一张照片上面,有三个谷仓(大小分别为2x1,2x5和1x1)和两头奶牛。 计算他的卫星照片中谷仓和奶牛的数量。
输入
行1:两个空格分隔的整数:N和M(N,M<=80)。
行2…N + 1:行i + 1表示照片的行i包含M个字符(且不含空格)。
输出
行1:照片中的谷仓数量。
行2:照片中的奶牛数量。
样例
输入
5 8
#####..#
#####.##
......#.
.###...#
.###..##
输出
2
2
AC代码
#include <bits/stdc++.h>
#define check(i, j) if (!d[i][j] && q[i][j] == '#') dfs(i, j)
using namespace std;
const int N = 100;
char q[N][N], d[N][N];
int n, m, area, cnt1, cnt2;
int minx, maxx, miny, maxy;
int dx[] = {0, 0, 1, 0, -1};
int dy[] = {0, 1, 0, -1, 0};
void init()
{
area = 0;
minx = miny = INT_MAX;
maxx = maxy = INT_MIN;
}
void check_area()
{
if ((maxx - minx + 1) * (maxy - miny + 1) == area) ++ cnt1;
else ++ cnt2;
}
void dfs(int x, int y)
{
d[x][y] = 1, ++ area;
minx = min(minx, x), maxx = max(maxx, x);
miny = min(miny, y), maxy = max(maxy, y);
for (int k = 1; k <= 4; ++ k)
check(x + dx[k], y + dy[k]);
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; ++ i)
for (int j = 1; j <= m; ++ j)
cin >> q[i][j];
for (int i = 1; i <= n; ++ i)
for (int j = 1; j <= m; ++ j)
if (!d[i][j] && q[i][j] == '#') {
init();
dfs(i, j);
check_area();
}
cout << cnt1 << endl << cnt2;
return 0;
}
题解
这道题目主要的难点在于怎么判断深搜的地方是矩形
,我们可以定义四个变量,分别存储矩形的边界点,我们只需要求出最小的x和y以及最大的x和y就可以知道四个点的坐标,当然计算坐标也没有必要。矩形的等价条件:得到的四个最值点运算求出面积与递归的面积相等
。
代码解释
根据上面的代码,给出适当的解释和注意点:
1.该题不能走重需要标记,我们存储两个数组,q和d,分别代表存储的地形和标记该点已经走过
2.输入的时候我们并没有字符串处理,直接存储字符也有字符的便利,不用判断点是否在边界(原因是:如果出边界,那么这点肯定不等于’#',而且也不用考虑越界)
3.一定要注意变量的正确使用周期,这里的init函数是重新初始化
4.方向变量不用多说,这里的采用的是宏check,我一般比较喜欢这个能减少变量的定义和复杂的方向变化代码量,并且判断后一并将dfs调用写入
5.判断面积,(maxx - minx + 1) * (maxy - miny + 1) 一定不要忘了+1,如果忘了你就一直wa吧 hh