这题还是很有意思的。
注意到题目里有一个关键信息:路肯定是贯穿了整张图的,所以实际上路把地图分成了几个区域:
1 1 0 1 1 0 0 1 1 1
1 1 0 1 1 0 0 1 1 1
1 1 0 1 1 0 0 1 1 1
1 1 0 1 1 0 0 1 1 1
1 1 0 1 1 0 0 1 1 1
1 1 0 1 1 0 0 1 1 1
1 1 0 1 1 0 0 1 1 1
0 0 0 0 0 0 0 0 0 0
1 1 0 1 1 0 0 1 1 1
1 1 0 1 1 0 0 1 1 1
(二值化之后的地图)
只要找到横纵方向的街区数,再相乘就好了。
如果真这么简单,岂不美哉。这题的特殊情况比较多,用化归的思想,在3x3区域内,我们可以找到所有的特殊情况。
难点1:街区计数器
我们要数出某一行/列里的街区数时,最先想到的应该是自动机。检查一下你的自动机能不能数出正确的街区数。
1 0 1(应为2个) 0 1 0(应为1个) 1 1 0 (应为1个) 1 1 1 (应为1个) 0 0 1(应为1个)
难点2:特殊情况
最自然的想法当然是只数第一列和第一行的街区数,再相乘,但是遇到这样的
0 0 0
1 1 1
1 1 1
显然就不对,只数第一行话就变成了0,但是实际上第二行有街区。
特别地,还有回字形的情况
0 0 0
0 1 0
0 0 0
所以我们应该逐行逐列去读街区数,取第一个非零的街区数作为行/列的街区数,因为只要出现了街区数不为0的行/列,往下的分布也是这样的(不排除底下还有零行,不过已经无所谓了)。
也可以数道路。
#include <stdio.h>
enum {
ROAD,BLOCK};
void preProcess(int**,int,int);//预处理函数,将读取的地图二值化,我们并不关心灰度值的具体数值,只需要知道它代表什么就行了
//这本篇0代表道路,1代表街区,与枚举变量保持一致
void debug_printSheet(int**,int,int);//打印当前的地图状态,有兴趣的可以把main里我注释掉的函数执行试试
int main()
{
int m,n,i,j,k,tmp;
scanf("%d%d",&m,&n);
int **mainPtr=(int**)malloc(sizeof(int*)*m)