【问题描述】
用一个二维方阵(最小为3X3,最大为9X9)表示一片海域。方阵中的元素只由0和1组成。1表示海岸线。计算水面面积(即:不在1围起来的区域中0的个数)。如下图所示6X6方阵表示的水面面积为14:
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 0 0
上述方阵表示的海域满足下面两个要求:
1、小岛只有一个。
2、用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 0 0
【输出样例】
14
【样例说明】
输入是6X6的方阵。该方阵中不在1围起来的区域中0的个数为14,所以输出的小岛面积为14。注意:最下方的三个元素1(即第5行第3列的1、第6行第2列的1、第6行第4列的1)组成了一个凹形的海岸线,第6行第3列的0不在海岸线内,所以应算作水面面积。
思路
对于方阵中的任意一个元素0,如果其位于同一行上的两个1之间,并且位于同一列上的两个1之间,则该元素肯定在1围起来的区域中。否则就不在1围起来的区域中,即属于水面。
所以先每行最远的两个1之间,不是1的数+2,再每列最远的两个1之间,不是1的数+2,所以4代表小岛,1代表海岸线,0和2代表水面(样例的结果如下图)
注:代码看似长,但遍历行和遍历列的代码相似,复制稍加修改即可
#include<stdio.h>
int main()
{
int n,a[10][10],i,j;
scanf("%d",&n);
for(i=0;i<n;i++)
for(j=0;j<n;j++)
scanf("%d",&a[i][j]);
int row1,row2,col1,col2;
for(i=0;i<n;i++)//行
{
for(j=0;j<n;j++)//第一个1
if(a[i][j]==1)
{
col1=j;
break;
}
for(j=n;j>=0;j--)//最后一个1
if(a[i][j]==1)
{
col2=j;
break;
}
for(j=col1+1;j<col2;j++)//两个1之间
if(a[i][j]!=1)
a[i][j]+=2;
}
for(j=0;j<n;j++)//列
{
for(i=0;i<n;i++)//第一个1
if(a[i][j]==1)
{
row1=i;
break;
}
for(i=n;i>=0;i--)//最后一个1
if(a[i][j]==1)
{
row2=i;
break;
}
for(i=row1+1;i<row2;i++)
if(a[i][j]!=1)
a[i][j]+=2;
}
int count=0;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
if(a[i][j]==0||a[i][j]==2)//4代表小岛,0和2代表水面
count++;
}
printf("%d\n",count);
return 0;
}