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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章