扫描线法

关于扫描线法

其实吧,扫描线法真的不难,有一点空间想象能力就够了......然而我一直没有去看。

就拿模板题来讲吧,给你一个边长为N的01矩阵,叫你求最大的全1矩阵面积。

以下说明BY YZX奆佬

对于20%的数据

直接暴力,时间复杂度O(C  O(R3C3) ,空间复杂度O(RCO(RC) 。

直接暴力枚举i,j,k,i,j,k,l ,分别枚举2个点的坐标,表示一个子矩阵。然后再枚举一下这个矩阵内的每个元素,将其的和求出来,最后取一个最大值。(注意需要判断一下枚举的矩阵中不能有破损的格子)

代码就不贴了(觉得太水(wu)了(liao))。

对于40%的数据

还是暴力,但是考虑优化掉求矩阵的和,时间复杂度O(C O(R2C2) ,空间复杂度O(3C O(3R2C2) 。

用一个二维数组储存输入。

用一个二维数组储存前缀和。

用一个二维数组储存0的个数的前缀和。

首先,还是暴力枚举i,j,k,i,j,k,l ,分别枚举2个点的坐标,表示一个组矩阵,然后再判断一下这个矩阵内是否有0(破损的格子),如果可以的话,更新ANS。

代码也就不贴了(因为本人太懒(ruo)了)。

对于100%的数据

扫描线法啦2333333。

这其实是一道模板题。

这有点难讲。

红色代表破损的格子。

alt

先枚举一层 R ,表示矩阵的第一行在第几行。

第二层枚举C C ,表示该行矩阵的该行的该结点左边有多少连续不为破损的格子。

然后再倒序枚举一次,求出右边有多少连续不为破损的格子。

然后再枚举一次,求出高度。

最后再枚举一次,更新anans 。

注意上面的都是同级的循环,所以复杂度为O(RCO(RC) 。

所以该矩阵的最大值为6。

alt

怎么样,看了是不是觉得很简单呢?但其实代码实现具有一定难度也很简单

//by myself 
#include<bits/stdc++.h>
using namespace std;
int N;
int LIS[155][155],lef[155],h[155],rig[155],MAXX;
int main()
{
	scanf("%d",&N);
	for (int i=1;i<=N;i++) for (int j=1;j<=N;j++) cin>>LIS[i][j];
	for (int i=1;i<=N;i++) lef[i]=1,rig[i]=N,h[i]=0;//初始化 
	
	for (int i=1;i<=N;i++)
	{
		int l=0,r=N+1;
		for (int j=1;j<=N;j++)
		{
			if (LIS[i][j]==0) h[j]=0,lef[j]=1,l=j;//碰到了0的点就清空所有并更新l的值 
			else h[j]++,lef[j]=max(lef[j],l+1);//若没有则继续扩散,并取lef的最大值 
		}
		for (int j=N;j>=1;j--)
		{
			if (LIS[i][j]==0) rig[j]=N,r=j;//同上 
			else rig[j]=min(rig[j],r-1),MAXX=max(MAXX,h[j]*(rig[j]-lef[j]+1));//同上但取最小值并更新MAXX=高度*(右边界-左边界+1)
 
		}
	}
	cout<<MAXX<<endl;
	return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/GREED-VI/p/9887399.html