Largest Allowed Area(二维前缀和+二分)

Largest Allowed Area

Gym - 102091L 

A company is looking for land to build its headquarters. It has a lot of money and can buy as 
many land patches as it needs. Its goal, however, is finding the largest square region 
containing no forest. Unfortunately, there is no such region that is large enough for the 
headquarters they want to build.
After negotiation with the government and the evaluation of environmental impacts, the 
government allows the company to purchase land with at most one forest patch. In other 
words, the company’s goal is now finding the largest square region containing at most one 
forest patch.
To facilitate the search process, the company creates a map in the form of a 2D table 
consisting R rows and C columns. In this 2D table, each entry represents a land of patch 
where 0 corresponds to a non-forest patch and 1 to a forest patch. Unfortunately, the map 
may have up to 1,000 x 1,000 entries and it is not a good idea to manually look for the largest 
allowed square region. This is where your skill comes into play. Write an efficient algorithm 
to find such a square region.


Input:
The first line is a positive integer T <= 20 representing the number of test cases. For each 
case, the input is formatted as follows.
First line R C
where R and C represents the number of rows and columns in the 
map. Also, 5 <= R, C <= 1,000
Next R lines Each line represents a row in the map from the first to last. It has C 
numbers which are 0 or 1, separated by one space.
Note: there is at least one non-forest patch in each test case.
Output:
There are T lines in the output. Each line is the number of rows in the largest allowed square 
region for each case.
2018 ICPC
Asia Nakhon Pathom
Regional Contest
Problem L
Largest Allowed Area
Time Limit 1 sec
2018 ICPC Asia Nakhon Pathom Regional Contest
Sample Input/Output
Input Output
2
10 20
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
20 10
1 0 0 0 0 1 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
1 0 0 0 0 0 0 0 1 0 
0 0 1 0 0 0 0 1 1 0 
0 0 0 0 0 0 0 0 0 1 
0 0 0 0 0 0 0 0 0 1 
0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 1 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 1 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 1 0 0 0 1 0 0 0 
0 0 0 0 0 0 0 0 0 0

https://vjudge.net/contest/326230#problem/L

题意:求一个最大正方形矩阵,矩阵和不超过1

 

二维前缀和递推公式:dp[i][j] = dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+map[i][j]

求x1,y1到x2,y2的区间和:ans = dp[x2][y2]-dp[x2][y1-1]-dp[x1-1][y2]+dp[x1-1][x2-1]

 

先求出二维前缀和,再对正方形的边长二分找到答案

#include<bits/stdc++.h>
using namespace std;

int a[1200][1200],dp[1200][1200],n,m;

bool Find(int num)
{

    for(int i = 1; i <=n; i ++)
    {
        if(i+num-1> n)
            break;
        for(int j = 1; j <= m; j ++)
        {
            if(j+num-1> m)
                break;
            int sum = dp[i+num-1][j+num-1]+dp[i-1][j-1]-dp[i+num-1][j-1]-dp[i-1][j+num-1];
            if(sum <= 1)
                return 1;
        }
    }
    return 0;
}

int main()
{
    int i,j,t;
    char ch;
    scanf("%d",&t);
    while(t --)
    {
        scanf("%d %d",&n, &m);
        for(i = 1; i <= max(n,m); i ++)
        {
            dp[i][0] = dp[0][i] = 0;
        }
        for(i = 1; i <= n; i ++)
        {
            for(j = 1; j <= m; j ++)
            {
            ch = getchar();
            while(ch!='0'&&ch!='1')
            ch = getchar();
            a[i][j] = ch-'0';

            }
        }

        for(i = 1; i <= n; i ++)
        {
            for(j = 1; j <= m; j ++)
            {
                dp[i][j] = dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+a[i][j];
            }
        }

        int l = 1;
        int r = min(n,m);
        int ans = -1;
        while(l <= r)
        {
            int mid = (l+r)>>1;
            if(Find(mid))
            {
                ans = mid;
                l = mid+1;
            }
            else
                r = mid-1;
        }
        printf("%d\n",ans);


    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值