题目集9:2 子区域计数

题目

由于防控形势严峻,现在z市已经开始了全区域的网格化封控管理。该市的区域可以看成一个矩形,其中所有主干道都是水平或垂直的,并且贯穿整个区域。如图所示,黑色表示城区的边界,红色表示城区的主干道,其中边界和主干道宽度都为1,且不存在边界与主干道、主干道与主干道相邻的情况。

无标题.png

为了方便网格化管理,我们定义网格单元是由城区边界或主干道围成的区域,且任意网格单元内不能包含主干道。上图中,该城区共被分割成了16个网格单元。

同时,网格化管理的本质思想是“分治”,不同的划分粒度对于管理效率会产生深远的影响。所以,这次W同学思考的不仅仅是网格单元,而是子网格。

子网格的定义为:子网格也是一个矩形,且子网格矩形4个角的对应点都位于边界与边界、边界与主干道、主干道与主干道的交点上。我们认为两个子网格是相同的,当且仅当两个子网格的4个角对应点全部重合。根据这个定义,我们可以知道,任意的网格单元也是一种子网格,整个城区的矩形也是一种特殊的子网格。

同样给出上述的图像,你能否帮小W计算下,有多少种可能的子网格?

输入格式:

第一行输入两个整数n,m(3≤n,m≤100)
其后n行,每行m个字符,字符有*#两种。*代表城区边界或主干道,#代表网格单元内区域。

输出格式:

输出一行一个整数,代表符合条件不同子网格的个数。

输入样例:

3 7
*******
*##*##*
*******

输出样例:

3

题解

分析

我的代码

吐槽

代码运行超时了

#include<stdio.h>
#include<stdbool.h>

bool flag(int x1, int y1, int x2, int y2,char str[][1000]);
int main()
{
	/*
	* 主要思路:把输入的看成一个字母矩阵,从中选择矩阵
	* 这个矩阵有一个要求:边上是'*',矩阵内部有'#'
	*/
	char str[1000][1000];
	int n, m, count = 0;
	scanf("%d %d", &n, &m);
	for (int i = 0; i < n; i++)
	{
		scanf("%s", str[i]);
	}
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < m; j++)
		{
			for (int k = i+2; k < n; k++)
			{
				for (int l = j+2; l < m; l++)
				{
					if (flag(i,j,k,l,str))
					{
						count++;
					}
				}
			}
		}
	}
	printf("%d", count);
	return 0;
}
bool flag(int x1, int y1, int x2, int y2, char str[][1000])
{
	bool a = false, b = true, c = true, isbreak = false;
	for (int i = x1+1; i < x2; i++)
	{
		for (int j = y1+1; j < y2; j++)
		{
			if (str[i][j] == '#')
			{
				a = true;
				isbreak = true;
				break;
			}
		}
		if (isbreak)
		{
			break;
		}
	}
	for (int i = y1; i <= y2; i++)
	{
		if (str[x1][i] == '#' || str[x2][i] == '#')
		{
			b = false;
		}
	}
	for (int i = x1; i <= x2; i++)
	{
		if (str[i][y1] == '#' || str[i][y2] == '#')
		{
			c = false;
		}
	}
	if (a&&b&&c)
	{
		return true;
	}
	else
	{
		return false;
	}
}

代码

对于第一次的代码,判断函数改成两个判断函数,不符合条件时直接return。这样就能加快运行速度了。

#include<stdio.h>
#include<stdbool.h>

bool flag_1 (int x1, int y1, int x2, int y2, char str[][1000]);
bool flag_2(int x1, int y1, int x2, int y2, char str[][1000]);
int main()
{
	/*
	* 主要思路:把输入的看成一个字母矩阵,从中选择矩阵
	* 这个矩阵有一个要求:边上是'*',矩阵内部有'#'
	*/
	char str[1000][1000];
	int n, m, count = 0;
	scanf("%d %d", &n, &m);
	for (int i = 0; i < n; i++)
	{
		scanf("%s", str[i]);
	}
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < m; j++)
		{
			for (int k = i + 2; k < n; k++)
			{
				for (int l = j + 2; l < m; l++)
				{
					if (flag_1(i, j, k, l, str) && flag_2(i, j, k, l, str))
					{
						count++;
					}
				}
			}
		}
	}
	printf("%d", count);
	return 0;
}
bool flag_1 (int x1, int y1, int x2, int y2, char str[][1000])
{
	bool a = false, b = true, c = true, isbreak = false;
	for (int i = x1 + 1; i < x2; i++)
	{
		for (int j = y1 + 1; j < y2; j++)
		{
			if (str[i][j] == '#')
			{
				return true;
			}
		}
	}
	return false;
}
bool flag_2(int x1, int y1, int x2, int y2, char str[][1000])
{
	for (int i = y1; i <= y2; i++)
	{
		if (str[x1][i] == '#' || str[x2][i] == '#')
		{
			return false;
		}
	}
	for (int i = x1; i <= x2; i++)
	{
		if (str[i][y1] == '#' || str[i][y2] == '#')
		{
			return false;
		}
	}
	return true;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值