本来一个很简单的题因为一个极其愚蠢的错误卡了非常久……
题目描述
输入: 输入n+1行,第一行为正整数n,表示地图的大小,n<=100
之后n行每行输入n个字符,由*和#组成,其中*表示海洋,#表示陆地
两块陆地在上下左右四个方向上有间接接壤视为同属于一个大陆
例如
*#
#*
视为拥有两块大陆
输出: 有多少块大陆
输入样例
5
*###*
**##*
#****
#*#**
***##
输出样例
4
思路
每碰到一块大陆,就计数,然后把这一整块大陆变成海洋,使其不对后续的计数产生干扰。
由于某一块大陆可能有非常多的土地接壤,考虑用递归来实现所有陆地的反转。
符号并不重要,将地图二值化,*->0->海洋,#->1->陆地
采用加边法来规避数组越界的问题,将实际操作的范围规定为[1,n]*[1,n]而非从0开始计数,虽然浪费了空间,但是使得i-1和j-1的访问在物理上不会越界,不会导致程序卡死的问题,同时也简化了程序设计的逻辑。
尬点
读入时需要注意n后的回车要吃掉,每行字符串后面的回车也要吃掉,否则会导致读入的数组不正常。
之前卡了很长一段时间,是因为我在定义了一个全局变量n之后,写主函数时又手贱定义了一个n。
根据语法,这没有任何错误,在局部变量与全局变量重名时,函数内使用局部变量,这是语言的特性,也不止C有。
可是这就导致读入的n并没有保存到全局的n中,子函数中访问到的n都是0,于是全部都工作不正常,都没输出……
我还纳闷咋没输出……还以为是递归的问题,调了半天,后来尝试想把打印数组的过程写成子函数的时候发现了错误。实属hape。
参考
和过去的两个题有点像,特别是前者。
计算机导论模拟测试练习(2018年秋)I. 灯矩阵
第四次机考(2019)D. 卫星照片二
#include <stdio.h>
#define MAX 100
int n;
int map[MAX+2][MAX+2]={0};
void reverse(int i,int j);
int main(int argc, char const *argv[])
{
int i,j,cnt=0;
char ch;
scanf("%d",&n);getchar();
for(i=1;i<=n;++i)
for(j=1;j<=n;++j)
{
ch=getchar();
if(j==n) getchar();
map[i][j]=(ch=='*')?0:1;
}
for(i=1;i<=n;++i)
for(j=1;j<=n;++j)
if(map[i][j])
{
++cnt;
reverse(i,j);
}
printf("%d\n",cnt );
return 0;
}
void reverse(int i,int j)
{
if(i<1||j<1||i>n||j>n) return ;
map[i][j]=0;
if(map[i-1][j]) reverse(i-1,j);
if(map[i+1][j]) reverse(i+1,j);
if(map[i][j-1]) reverse(i,j-1);
if(map[i][j+1]) reverse(i,j+1);
}