2018 ICPC Asia Nakhon Pathom Regional Contest L – Largest Allowed Area

题意

给定一个 r 行 c 列的 01 矩阵,求至多包含一个1的正方形子矩阵的最大边长。

思路

使用前缀和维护矩阵,可以在 O ( 1 ) O( 1 ) O(1) 的时间计算任意子矩阵中 1 的个数。

枚举所有的点,对于点 ( i , j ) ( i , j ) (i,j),二分所有以该点为左上角的正方形子矩阵的边长,找到满足条件的最大正方形的边长。

总体复杂度为 O ( T ∗ n 2 l o g n ) O( T * n^2logn ) O(Tn2logn),本道题目卡常,需要用到快读等算法,并对绝对时间进行极致的优化。

代码

#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn = 1010;

int r, c;
int g[maxn][maxn];
int s[maxn][maxn];

#define get(x1, y1, x2, y2) (s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1])

int bsearch_2(int x, int y, int l, int r){
    while(l < r){
        int mid = l + r + 1 >> 1;
        if(get(x, y, x + mid -1, y + mid - 1) <= 1) l = mid;
        else r = mid-1;
    }
    return l;
}

int read() {
    char c; int num, f = 1;
    while(c = getchar(),!isdigit(c)) if(c == '-') f = -1; num = c - '0';
    while(c = getchar(), isdigit(c)) num = num * 10 + c - '0';
    return f * num;
}

signed main() {

#ifdef LOCAL
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif

    int t; t = read();
    while(t--){

        r = read(); c = read();
        for(int i = 1; i<=r; i++){
            for(int j = 1; j<=c; j++){
                g[i][j] = read();
                s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + g[i][j];
            }
        }

        int ans = 0;
        for(int i = 1; i<=r; i++){
            for(int j = 1; j<=c; j++){
                int max_r = min(r-i +1, c-j+1);
                int l = bsearch_2(i, j, ans+1, max_r);
                if(i+l-1<=r && j+l-1<=c && get(i, j, i+l-1, j+l-1) <= 1){
                    ans = max(ans, l);
                }
            }
        }
        printf("%d\n", ans);

    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FengLing255

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值