悬线法

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)

以上是关于悬线法的主要内容,如果未能解决你的问题,请参考以下文章

bzoj3039玉蟾宫 悬线法

悬线法

动态规划之悬线法

悬线法

悬线法dp

动态规划悬线法