码迷,mamicode.com
首页 > 其他好文 > 详细

悬线法

时间:2019-11-03 13:07:01      阅读:96      评论:0      收藏:0      [点我收藏+]

标签:方向   usaco   转移   ++   矩阵   时间   i++   要求   code   

  我们有时会遇到这样一类问题:在一个大矩阵中求出满足某些限制的最大子矩阵。使用悬线法可以在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)

悬线法

标签:方向   usaco   转移   ++   矩阵   时间   i++   要求   code   

原文地址:https://www.cnblogs.com/doyo2019/p/11785595.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!