悬线法
Posted doyo2019
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了悬线法相关的知识,希望对你有一定的参考价值。
我们有时会遇到这样一类问题:在一个大矩阵中求出满足某些限制的最大子矩阵。使用悬线法可以在O(n2)的时间内求解这类问题。
要知道最大子矩阵的大小,我们只要求出其上下左右四个方向上的边界就可以了。使用悬线法时,我们枚举每一行i,计算以i为下边界的最大子矩阵,再计算对于每一个位置,包含它的最大子矩阵的边界。于是问题就变成了从每一个位置,向上/左/右走到什么位置时不合法。对于每一个位置,我们实际上可以O(1)求出这些信息,因为有这样一个显然的结论:如果它在上/左/右的方向上的前一个位置合法,那么它的信息就可以从这个位置的信息转移过来。但这样求出的这些信息不一定是一个合法子矩阵的三个边界,因为它没有考虑前几行内是否会有不合法的位置,所以我们还要用前一行算出的边界对它进行限制,这样才可以得到一个合法的子矩阵。
放上代码:
for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(!a[i][j]) continue;l[i][j]=j; if(a[i][j-1]) l[i][j]=l[i][j-1]; }//计算向左能走到哪里 for(int j=m;j>=1;j--){ if(!a[i][j]) continue;r[i][j]=j; if(a[i][j+1]) r[i][j]=r[i][j+1]; }//计算向右能走到哪里 for(int j=1;j<=m;j++){ if(!a[i][j]) continue;f[i][j]=i; if(a[i-1][j]){ f[i][j]=f[i-1][j]; l[i][j]=max(l[i][j],l[i-1][j]); r[i][j]=min(r[i][j],r[i-1][j]);//用上一行的边界进行限制 }//计算向上能走到哪里 int x=f[i][j]-1,y=l[i][j]-1,z=r[i][j]; ans=max(ans,s[i][z]-s[i][y]-s[x][z]+s[x][y]);//更新答案 } }
例题:
WOJ#1742 棋盘制作(zjoi2007)
WOJ#1315 糖果盒 ( Candy Box )
WOJ#1787 Big Barn 巨大的牛棚(USACO Training Section 5.3)
以上是关于悬线法的主要内容,如果未能解决你的问题,请参考以下文章