问题描述
用一个二维方阵(最小为3X3,最大为9X9)表示一片海域。方阵中的元素只由0和1组成。1表示海岸线。计算由海岸线围起来的小岛面积(即:由1围起来的区域中0的个数)。如下图所示6X6方阵表示的小岛面积为9:
0 0 0 1 0 0
0 0 1 0 1 0
0 1 0 0 0 1
1 0 0 0 1 0
1 0 1 0 1 0
1 1 0 1 1 1
上述方阵表示的海域满足下面两个要求:
1、小岛只有一个。
2、用1表示的海岸线肯定可以封闭成一个小岛,但有可能是凸的,也有可能是凹的。所以在判断时:对于方阵中的任意一个元素0,如果其位于同一行上的两个1之间,并且位于同一列上的两个1之间,则该元素肯定在1围起来的区域中。不符合该规定的其它情况不考虑。
【输入形式】
先从标准输入中输入方阵的阶数,然后从下一行开始输入方阵的元素(只会输入0或1),各元素之间以一个空格分隔,每行最后一个元素后没有空格,但会有回车换行符。
【输出形式】
在标准输出上输出用整数表示的小岛面积。
【输入样例】
6
0 0 0 1 0 0
0 0 1 0 1 0
0 1 0 0 0 1
1 0 0 0 1 0
1 0 1 0 1 0
1 1 0 1 1 1
【输出样例】
9
【样例说明】
输入是6X6的方阵。该方阵中由1围起来的区域内有9个0,所以输出的小岛面积为9。注意:最下方的三个元素1(即第5行第3列的1、第6行第2列的1、第6行第4列的1)组成了一个凹形的海岸线,第6行第3列的0不在海岸线内,所以不应算作小岛面积。
解题思路
其实这一题思路很简单的,题目中也已经给出了判断一个点为小岛的方法。
对于方阵中的任意一个元素0,如果其位于同一行上的两个1之间,并且位于同一列上的两个1之间,则该元素肯定在1围起来的区域中。不符合该规定的其它情况不考虑。
我们只需要遍历所有的非边界点,并判断每个点是否满足上述的条件即可。嘴上这么说,但是在实现的时候,确实出现了一些问题。
我将所有的点存入了一个二维数组中,在对每个点进行遍历的时候,想通过一个函数来实现判断。
cin>>n;
int graph[n][n];
int s=0;
for(i=0;i<n;i++){
for(j=0;j<n;j++){
cin>>graph[i][j];
}
}
但是函数传入二位参数比较复杂,或者就需要共有多少列元素,不能满足设计需求,此处想到一个折中的方法,即函数的输入输出分别如下:
- 输入:二维数组的一列或一行,待判定元素在该列或行中的位置,该列或行共有元素个数
- 输出:若为小岛,则输出true,反之输出false
但是在如何传入二维数组的某列或某行时,出现了问题。最终无奈选择了如下的实现方式。
for(i=1;i<n-1;i++){
for(j=1;j<n-1;j++){
if(graph[i][j]==0&&yjudge(graph[0]+j,i,n)&&xjudge(graph[i],j,n))//当某点的元素为0且该行和列满足要求时
s++;
}
}
其中graph[0]+j本意想实现传入小岛某一列的目标,但最后发现,该传参方法要想实现对某一列元素的遍历,需要按照下述方法进行遍历:
bool yjudge(int graph[],int i,int n){
int temp;
for(temp=0;temp<i;temp++){
if(graph[temp*n]==1){//当访问某列的下一个元素时,需要向下取n个元素进行访问。
for(temp=i+1;temp<n;temp++){
if(graph[temp*n]==1){
return true;
}
}
}
}
return false;
}
二维数组在计算机中是按照如下方式进行存储的
因此当需要访问某列的元素时,需要向下访问该行元素的个数。
对于某行元素的判断函数如下:
bool xjudge(int graph[],int i,int n){
int temp;
for(temp=0;temp<i;temp++){
if(graph[temp]==1){
for(temp=i+1;temp<n;temp++){
if(graph[temp]==1){
return true;
}
}
}
}
return false;
}
在这里也希望路过的各位有更好的方法可以留言分享~