1. 程式人生 > >帶限制條件的最大子矩陣 - 牛客

帶限制條件的最大子矩陣 - 牛客

ott boa desc pen eight tps 子矩陣 列數 const

鏈接: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
9
≤  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 \n", i, j, k, ans, l, r);
            }
        }
    }
    printf("%lld\n", ans);
    return 0;
}

帶限制條件的最大子矩陣 - 牛客