zoukankan      html  css  js  c++  java
  • 带限制条件的最大子矩阵

    链接: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.
    -10
    ≤  M
    i,j  
    ≤ 10
    9

    输出描述:

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

    输入

    复制
    5 5 3 3 4
    0 0 10 0 0
    3 4 0 2 3
    -1 3 0 -8 3
    0 0 32 -9 3
    3 0 45 3 0

    输出

    复制
    82
    示例2

    输入

    复制
    2 2 2 2 2
    -1 -1
    -1 -1

    输出

    复制
    0

    题意 : 在一个大的矩阵中寻找一个小的矩阵,但是行列是有要求的。
    思路分析: 枚举行的起点和终点,复杂度是 O(n^2) , 通过预处理前缀和,可以得到此时的一行的数,再O(n)的用单调队列搞一下即可
    代码示例 : (WA 了 , 还在调试中 )
    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    const ll maxn = 1e6+5;
    typedef pair<ll, ll>pa;
    
    ll n, m;
    ll x, y, z;
    ll mp[505][505], sum[505][505], cnt[505][505], ze[505][505];
    ll f[505], f2[505];
    pa que[2005];
    
    int main() {
        //freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
        
        cin >> n >> m >> x >> y >> z;
        for(ll i = 1; i <= n; i++){
            for(ll j = 1; j <= m; j++){
                scanf("%lld", &mp[i][j]);
                if (mp[i][j] == 0) ze[i][j] = 1;
            }
        }    
        for(ll i = 1; i <= n; i++){
            for(ll j = 1; j <= m; j++){
                cnt[i][j] = cnt[i-1][j]+ze[i][j];
                sum[i][j] = sum[i-1][j]+mp[i][j];
            }
        } 
    
        ll ans = 0;
        for(ll i = 1; i <= n; i++){
            for(ll j = i; j <= n; j++){
                if (j-i+1 > x) break;
                ll l=0, r = 0 ;
                memset(que, 0, sizeof(que));
                memset(f, 0, sizeof(f));
                memset(f2, 0, sizeof(f2));
                for(ll k = 1; k <= m; k++){
                    ll num = sum[j][k]-sum[i-1][k];
                    ll zero = cnt[j][k]-cnt[i-1][k];
                    f[k] = f[k-1]+num;                
                    f2[k] = f2[k-1]+zero;
    
                    while (l < r && que[r-1].first > f[k]){
                        r--;
                    }
                    que[r++] = make_pair(f[k], k);
                    
                    while(l < r && k-que[l].second+1 > y) {l++; }
                    while(l < r && f2[k]-f2[que[l].second-1] > z) {l++; }
                    if (l< r) ans = max(ans, f[k]-f[que[l].second-1]);
                    
                    //prllf("%lld %lld %lld %lld  l = %lld r = %lld 
    ", i, j, k, ans, l, r);
                }
            }
        }
        printf("%lld
    ", ans);
        return 0;
    }
    
    东北日出西边雨 道是无情却有情
  • 相关阅读:
    杭电1058
    动态规划之背包模版
    按字典序依次打印只由1~n组成的n位数
    杭电1029
    杭电1257
    杭电2191
    杭电1114
    杭电2602
    南阳975
    杭电2138
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/9383955.html
Copyright © 2011-2022 走看看