关于扫描线法
其实吧,扫描线法真的不难,有一点空间想象能力就够了......然而我一直没有去看。
就拿模板题来讲吧,给你一个边长为N的01矩阵,叫你求最大的全1矩阵面积。
以下说明BY YZX奆佬
对于20%的数据
直接暴力,时间复杂度O(R 3 C 3 ) O(R3C3) ,空间复杂度O(RC) O(RC) 。
直接暴力枚举i,j,k,l i,j,k,l ,分别枚举2个点的坐标,表示一个子矩阵。然后再枚举一下这个矩阵内的每个元素,将其的和求出来,最后取一个最大值。(注意需要判断一下枚举的矩阵中不能有破损的格子)
代码就不贴了(觉得太水(wu)了(liao))。
对于40%的数据
还是暴力,但是考虑优化掉求矩阵的和,时间复杂度O(R 2 C 2 ) O(R2C2) ,空间复杂度O(3R 2 C 2 ) O(3R2C2) 。
用一个二维数组储存输入。
用一个二维数组储存前缀和。
用一个二维数组储存0的个数的前缀和。
首先,还是暴力枚举i,j,k,l i,j,k,l ,分别枚举2个点的坐标,表示一个组矩阵,然后再判断一下这个矩阵内是否有0(破损的格子),如果可以的话,更新ANS。
代码也就不贴了(因为本人太懒(ruo)了)。
对于100%的数据
扫描线法啦2333333。
这其实是一道模板题。
这有点难讲。
红色代表破损的格子。
先枚举一层R R ,表示矩阵的第一行在第几行。
第二层枚举C C ,表示该行矩阵的该行的该结点左边有多少连续不为破损的格子。
然后再倒序枚举一次,求出右边有多少连续不为破损的格子。
然后再枚举一次,求出高度。
最后再枚举一次,更新ans ans 。
注意上面的都是同级的循环,所以复杂度为O(RC) O(RC) 。
所以该矩阵的最大值为6。
怎么样,看了是不是觉得很简单呢?但其实代码实现具有一定难度也很简单
//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; }