面积计算

简介: 编程计算由“*”号围成的下列图形的面积。面积计算方法是统计*号所围成的闭合曲线中水平线和垂直线交点的数目。如下图所示,在10*10的二维数组中,有“*”围住了15个0,因此面积为15。首先输入m和n表示二维数组的行和列数目,然后输入m*n的二维数组,其中的*用1表示。

编程计算由“*”号围成的下列图形的面积。面积计算方法是统计*号所围成的闭合曲线中水平线和垂直线交点的数目。如下图所示,在10*10的二维数组中,有“*”围住了15个0,因此面积为15。
首先输入m和n表示二维数组的行和列数目,然后输入m*n的二维数组,其中的*用1表示。

0 0 0 0 0 0 0 0 0 0
0 0 0 0 * * * 0 0 0
0 0 0 0 * 0 0 * 0 0
0 0 0 0 0 * 0 0 * 0
0 0 * 0 0 0 * 0 * 0
0 * 0 * 0 * 0 0 * 0
0 * 0 0 * * 0 * * 0
0 0 * 0 0 0 0 * 0 0
0 0 0 * * * * * 0 0
0 0 0 0 0 0 0 0 0 0
【样例输入】area.in
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
【样例输出】area.out
15

算法思路1:
参考:http://blog.csdn.net/harlow_cheng/article/details/51889928?locationNum=9
把1看成围墙,我们是想进入围墙的人,但是怎么也进不了,于是我们就在围墙的周围乱走,把能不进围墙就走到的地方走个遍。然而她就是这么无懈可击,我也真是醉了。然后删掉围墙。剩下的就是被围住的东西了,看得到,但是永远得不到,因为它们被围起来了。从每个角落都进行一次广搜,找连通块,找到了置为false就可以了。

说这么多啰嗦的废话,其实是这么个意思:

从左上角开始一行一行地扫描二维数组,对遇到的每一个0都做一次BFS,搜过的点标记为1。但是要注意:对每一行扫描时,若是遇到了围墙,就立即停止对这一行的扫描,接着扫描下一行。这样一来就可以把“围墙左侧”连通的0都变为1。

然后:从右下角开始对二维数组的每一行从右向左进行扫描,遇到0则做BFS,搜过的点标记1。同样地,每一行扫描时遇到围墙则该行扫描结束,进入下一行的扫描。
这样一来可以使得“围墙右侧”连通的0变为1。

最后:经过上面两个环节以后,数组中剩余的0应该都是围墙内的0。所以,扫描一遍二维数组,统计0的个数就是答案。

这个算法可以解决曲线(围墙)比较简单的情况。但是足以满足题目要求。

代码如下:

  1 #include <iostream>
  2 #include<queue>
  3 #include<stdio.h>
  4 using namespace std;
  5 
  6 #define localTest 1
  7 
  8 #define maxM 103
  9 #define maxN 103
 10 
 11 int m,n,a[maxM][maxN]={0};
 12 int dx[4]={-1,0,1,0};//上右下左
 13 int dy[4]={0,1,0,-1};
 14 
 15 void BFS(int x,int y);
 16 
 17 int main()
 18 {
 19     int i,j,ans=0;
 20     freopen("area_data/area5.in","r",stdin);
 21     scanf("%d%d",&m,&n);
 22     #ifdef localTest
 23     printf("%d %d\n",m,n);//
 24     #endif // localTest
 25     for(i=0;i<m;i++)
 26     {
 27             for(j=0;j<n;j++)
 28             {
 29                 scanf("%d",&a[i][j]);
 30                 #ifdef localTest
 31                 printf("%d ",a[i][j]);//
 32                 #endif // localTest
 33             }
 34             #ifdef localTest
 35             printf("\n");//
 36             #endif // localTest
 37     }
 38 
 39     for(i=0;i<m;i++)
 40     {
 41         for(j=0;j<n;j++)
 42         {
 43             if(a[i][j]==1) break;
 44             if(a[i][j]==0)
 45             {
 46                 BFS(i,j);
 47             }
 48         }
 49     }
 50     for(i=m-1;i>=0;i--)
 51     {
 52         for(j=n-1;j>=0;j--)
 53         {
 54             if(a[i][j]==1) break;
 55             if(a[i][j]==0)
 56             {
 57                 BFS(i,j);
 58             }
 59         }
 60     }
 61 
 62     #ifdef localTest
 63     printf("--------------\n");//
 64     #endif // localTest
 65     for(i=0;i<m;i++)
 66     {
 67         for(j=0;j<n;j++)
 68         {
 69             if(a[i][j]==0)ans++;
 70             #ifdef localTest
 71             printf("%d ",a[i][j]);//
 72             #endif // localTest
 73         }
 74         #ifdef localTest
 75         printf("\n");
 76         #endif // localTest
 77     }
 78     printf("%d\n",ans);
 79     return 0;
 80 }
 81 void BFS(int x,int y)
 82 {
 83     queue<int> qx,qy;
 84     int xx,yy,i;
 85 
 86     qx.push(x);
 87     qy.push(y);
 88     a[x][y]=1;
 89     while(!qx.empty())
 90     {
 91         for(i=0;i<4;i++)
 92         {
 93             xx=qx.front()+dx[i];
 94             yy=qy.front()+dy[i];
 95             if(xx>=0&&xx<m&&yy>=0&&yy<n&&a[xx][yy]==0)
 96             {
 97                 a[xx][yy]=1;
 98                 qx.push(xx); qy.push(yy);
 99             }
100         }
101         qx.pop(); qy.pop();
102     }
103 }

算法思路2:
参考:http://blog.csdn.net/u011123263/article/details/17249283
把边界的0全部赋值为-1,然后进行两次遍历,从上往下,在从下往上;
在遍历时,若当前位置为0,如果上,下,左,右有一个是-1,则把当前的0更改为-1;
遍历完后,再统计0的个数,就是所求的结果。

这个算法思路与算法思路1其实差不多,但是实现起来比较简单。

代码:

  1 #include<iostream>
  2 #include<stdio.h>
  3 using namespace std;
  4 
  5 #define localTest 1
  6 
  7 #define maxM 103
  8 #define maxN 103
  9 
 10 int m,n,a[maxM][maxN]={0};
 11 int dx[4]={-1,0,1,0};//上右下左
 12 int dy[4]={0,1,0,-1};
 13 
 14 int main()
 15 {
 16     int i,j,ans=0;
 17     int k,xx,yy;
 18     freopen("area_data/area5.in","r",stdin);
 19     scanf("%d%d",&m,&n);
 20     #ifdef localTest
 21     printf("%d %d\n",m,n);
 22     #endif // localTest
 23     for(i=0;i<m;i++)
 24     {
 25             for(j=0;j<n;j++)
 26             {
 27                 scanf("%d",&a[i][j]);
 28                 #ifdef localTest
 29                 printf("%2d ",a[i][j]);
 30                 #endif // localTest
 31             }
 32             #ifdef localTest
 33             printf("\n");
 34             #endif // localTest
 35     }
 36 
 37     for(i=0;i<m;i++)//把第0列和最后一列的0变为-1
 38     {
 39         if(a[i][0]==0) a[i][0]=-1;
 40         if(a[i][n-1]==0) a[i][n-1]=-1;
 41     }
 42     for(j=0;j<n;j++)//把第0行和最后一行的0变为-1
 43     {
 44         if(a[0][j]==0) a[0][j]=-1;
 45         if(a[m-1][j]==0) a[m-1][j]=-1;
 46     }
 47 
 48     for(i=1;i<m-1;i++)
 49     {
 50         for(j=1;j<n-1;j++)
 51         {
 52             if(a[i][j]==0)
 53             {
 54                 for(k=0;k<4;k++)
 55                 {
 56                     xx=i+dx[k]; yy=j+dy[k];
 57                     if(xx>=0&&xx<m&&yy>=0&&yy<n&&a[xx][yy]==-1)
 58                     {
 59                         a[i][j]=-1;
 60                         break;
 61                     }
 62                 }
 63             }
 64         }
 65     }
 66 
 67     for(i=m-1;i>=0;i--)
 68     {
 69         for(j=n-1;j>=0;j--)
 70         {
 71             if(a[i][j]==0)
 72             {
 73                 for(k=0;k<4;k++)
 74                 {
 75                     xx=i+dx[k]; yy=j+dy[k];
 76                     if(xx>=0&&xx<m&&yy>=0&&yy<n&&a[xx][yy]==-1)
 77                     {
 78                         a[i][j]=-1;
 79                         break;
 80                     }
 81                 }
 82             }
 83         }
 84     }
 85 
 86     #ifdef localTest
 87     printf("\n--------------\n");
 88     #endif // localTest
 89     for(i=0;i<m;i++)
 90     {
 91         for(j=0;j<n;j++)
 92         {
 93             if(a[i][j]==0)ans++;
 94             #ifdef localTest
 95             printf("%2d ",a[i][j]);
 96             #endif // localTest
 97         }
 98         #ifdef localTest
 99         printf("\n");
100         #endif // localTest
101     }
102     printf("%d\n",ans);
103     return 0;
104 }

 

后续:

为何要从左上角、右下角做两次的扫描呢?这个主要是考虑到有一些特殊情况下的输入。不多说,看下面这两组输入:

   

左边这组特殊的输入,在代码一当中,假如没有从右下角扫描处理“”围墙右侧”的0,则统计结果会多出一些0。所以需要从右下角再做一次扫描。

右侧这一组特殊的输入,在代码二中,假如只做左上角开始的扫描,那么中间那几个0会因为在检测到它们的时候,周围没有-1而保持0的值。所以要从右下角再做一次扫描。

 

相关文章
|
存储 JavaScript 前端开发
|
10月前
|
负载均衡 网络协议 网络性能优化
动态IP代理技术详解及网络性能优化
动态IP代理技术通过灵活更换IP地址,广泛应用于数据采集、网络安全测试等领域。本文详细解析其工作原理,涵盖HTTP、SOCKS代理及代理池的实现方法,并提供代码示例。同时探讨配置动态代理IP后如何通过智能调度、负载均衡、优化协议选择等方式提升网络性能,确保高效稳定的网络访问。
983 2
|
弹性计算 容灾 关系型数据库
阿里云服务器ECS中扩容云盘后磁盘容量没有增加的解决方法
ECS控制台操作扩容只是扩大云盘的存储容量,不会扩容ECS实例的文件系统。还需要登录实例,然后进行扩容文件系统的操作。
2060 0
阿里云服务器ECS中扩容云盘后磁盘容量没有增加的解决方法
|
前端开发 API 调度
React 之从 requestIdleCallback 到时间切片
在上篇《React 之 requestIdleCallback 来了解一下》,我们讲解了 requestIdleCallback 这个 API,它可以实现在浏览器空闲的时候执行代码,这就与 React 的理念非常相似,都希望执行的时候不影响到关键事件,比如动画和输入响应,但因为兼容性、requestIdleCallback 定位于执行后台和低优先级任务、执行频率等问题,React 在具体的实现中并未采用 requestIdleCallback,本篇我们来讲讲 React 是如何实现类似于 requestIdleCallback,在空闲时期执行代码的效果,并由此讲解时间切片的背后实现。
544 0
|
JavaScript Java 测试技术
基于springboot+vue.js的社区养老服务系统附带文章和源代码设计说明文档ppt
基于springboot+vue.js的社区养老服务系统附带文章和源代码设计说明文档ppt
185 0
|
编解码 前端开发 JavaScript
【长文慎入】一文吃透React SSR服务端同构渲染
前段时间一直在研究 react ssr技术,然后写了一个完整的 ssr开发骨架。今天写文,主要是把我的研究成果的精华内容整理落地,另外通过再次梳理希望发现更多优化的地方,也希望可以让更多的人少踩一些坑,让更多的人理解和掌握这个技术。 相信看过本文(前提是能对你的胃口,也能较好的消化吸收)你一定会对 react ssr服务端渲染技术有一个深入的理解,可以打造自己的脚手架,更可以用来改造自己的实际项目,当然这不仅限于 react ,其他框架都一样,毕竟原理都是相似的。
1655 0
|
Python
Python尝试访问不存在的属性或方法
【6月更文挑战第2天】
255 3
|
缓存 前端开发 JavaScript
|
存储
libjpeg库使用实例细节分析
libjpeg库使用实例细节分析
397 0
|
C语言
C语言打字游戏源码
C语言打字游戏源码
277 0