LA 3029 最大子矩阵 city game

题目大意
给定一个m*n的矩阵,其中一些池子是空地,其他事障碍,求出最大的空地面积并将结果乘以三。
分析
最常用的方法暴力枚举,枚举矩形的两个顶角坐标。,然后判断求面积,复杂度十分大,对于本题目的数据显然通过不了,我们采用扫描发法,把每个格子向上的连续空格看作一个悬线,并且用up(i,j),left(i,j),right(i,j分别表示可以向上的悬线长度,向左向右的最大边界,注意边界保留的是空地的下标,不是障碍的下标。这样的话每一个格子对应了以i行位下界,高度为up(i,j)左右边界分别是left(i,j)和right(i,j)的矩形,不难发现这些矩形中的最大面积就是所求。
那么这几个量如何更新呢
首先 如果当前格子不是障碍 up(i,j)=i==0?1:up(i-1,j)+1;
否则 up(i,j)=0;

left(i,j)=max(left(i-1,j),lo+1); lo是最左的障碍,初始为-1
right(i,j)=min{right(i-1,j),ro-1} ro是最右的障碍,初始为n
上代码

#include<iostream>
#include<algorithm>
#define maxn 1000+10
using namespace std;

int le[maxn][maxn], ri[maxn][maxn], up[maxn][maxn];
int q[maxn][maxn];
int lo, ro;

int main()
{
	int  T;
	cin >> T;
	while (T--)
	{
		int n, m;
		cin >> m >> n;

		int ans = 0;
		char ch;
		for (int i = 0; i < m; i++)
			for (int j = 0; j < n; j++)
			{
				cin >> ch;
				if (ch == 'F')		q[i][j] = 1;        //障碍为0,空地为1
				else if (ch == 'R')	q[i][j] = 0;
			}
		/*for (int i = 0; i < m; i++)
		{
			for (int j = 0; j < n; j++)
				cout << q[i][j]<<" ";
			cout << endl;

		}*/
		for (int i = 0; i < m; i++)
		{
			lo =-1, ro = n;
			for (int j = 0; j < n; j++)				//更新up(i,j)和lo(i,j)
			{
				if (q[i][j])
				{
					up[i][j] = i == 0 ? 1 : up[i - 1][j]+1;
					le[i][j] = i == 0 ? lo+1 : max(lo + 1, le[i - 1][j]);
				}
				else
				{
					up[i][j] = le[i][j] = 0;
					lo = j;
				}
			}
			for (int j = n - 1; j >= 0; j--)  
			{
				if (q[i][j])
				{
					ri[i][j] = i == 0 ? ro-1 : min(ro-1, ri[i - 1][j]);
					ans = max(ans, up[i][j] * (ri[i][j] - le[i][j] + 1));
				}
				else
					ro = j, ri[i][j] = n;
			}

		}
		cout << ans * 3 << endl;

	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值