首页 > 其他 > 详细

B-矩阵

时间:2018-07-07 21:26:09      阅读:156      评论:0      收藏:0      [点我收藏+]

链接:https://www.nowcoder.com/acm/contest/131/B
来源:牛客网

矩阵 M 包含 R 行 C 列,第 i 行第 j 列的值为 Mi,j
请寻找一个子矩阵,使得这个子矩阵的和最大,且满足以下三个条件:
子矩阵的行数不能超过 X 行。
子矩阵的列数不能超过 Y 列。
子矩阵中 0 的个数不能超过 Z 个。
请输出满足以上条件的最大子矩阵和。

输入描述:

第一行输入五个整数 R,C,X,Y,Z。
接下来 N 行,每行输入 M 个整数,第 i 行第 j 列的整数表示 Mi,j
1 ≤ R,C ≤ 500.
1 ≤ X ≤ R.
1 ≤ Y ≤ C.
1 ≤ Z ≤ R x C.

|Mij|<=1e9

输出描述:

输出满足以上条件的最大子矩阵和。


考虑枚举行数。
枚举行数后枚举从哪行开始。
预处理出来纵向前缀和,然后枚举的时候就把每一个元素转化成柱形图那样的格式,然后求最大值就好了。

求最大值时的思想是枚举最后一个元素,然后看前面的元素,前面元素大于0直接放,小于0的就把队尾取出来,加到这个元素,直到不小于0或者队列为空位置。
以数结尾的最大值是目前队列元素里面的和。

用单调栈也可以做。


#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int N=508;
int q[N],p[N],zt[N][N],L[N];
long long mp[N][N],up[N][N],a[N];
int R,C,X,Y,Z;
long long work(){
    for(int i=1;i<=C;++i) p[i]=i;
    int h=1,r=0;
    long long ans=0,sum=0;
    q[1]=0;
    for(int i=1;i<=C;++i) 
    {
        while(h<=r&&p[q[h]]<=i-Y) sum-=a[q[h++]];
        while(h<=r&&a[i]<0) {
            sum-=a[q[r]];        
            a[i]+=a[q[r]];
            p[i]=p[q[r--]];
        }
        if(a[i]>0) sum+=a[i],q[++r]=i;    
        while(h<=r&&(L[i]-L[p[q[h]]]>Z)) sum-=a[q[h++]];
        ans=max(ans,sum);
    }
    return ans;
}
int main(){
    long long ans=0;
    scanf("%d%d%d%d%d",&R,&C,&X,&Y,&Z);
    for(int i=1;i<=R;++i) for(int j=1;j<=C;++j) scanf("%lld",&mp[i][j]);
    for(int i=1;i<=R;++i) for(int j=1;j<=C;++j) up[i][j]=up[i-1][j]+mp[i][j],zt[i][j]=zt[i-1][j]+(mp[i][j]==0);
    for(int len=1;len<=X;++len){
        for(int i=1;i<=R-len+1;++i){
            for(int j=1;j<=C;++j) a[j]=up[i+len-1][j]-up[i-1][j],L[j]=zt[i+len-1][j]-zt[i-1][j];
            for(int j=2;j<=C;++j) L[j]+=L[j-1];
            ans=max(ans,work());
        }
    }
    printf("%lld\n",ans);
}

 

B-矩阵

原文:https://www.cnblogs.com/mfys/p/9278152.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!