题目:2018 ICPC Asia Nakhon Pathom Regional Contest Problem L Largest Allowed Area
题意描述:
一家公司想找一块正方形的地来建设总部,这块地只能包含一块林地。即给你n和m,表示地的长和宽。接下来给你nxm的矩阵,矩阵元素由0和1组成。0表示空地,1表示林地。要你从这块地中选出一个最大的正方形的地,这块地中最多只能包含一块林地。输出这个正方形的边长。
题目分析:
因为这块地中最多可以包含一块林地,所以可以用二维差分来判断一块地中有多少个林地。而这道题n和m的范围都是1000,而且想要的地是正方形,所以我们用二分来判断到某个点可以得到的最大正方形,时间复杂度为n^2*logn.这道题目的输入样例有20,那最坏的情况为20*1000*1000 = 2E7.输入比较大,所以还要用到输入挂来优化输入,而且用一般的读入挂还不行,我试了几个读入挂了,只有下面这个可以,不过下面这个读入挂本地是跑不出结果的。(做的是时候就是卡这里了,咕咕)。
代码:
#include<bits/stdc++.h>
using namespace std;
int sum[1005][1005], a[1005][1005];
namespace fastIO {
#define BUF_SIZE 100000
//fread -> read
bool IOerror = 0;
inline char nc() {
static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
if(p1 == pend) {
p1 = buf;
pend = buf + fread(buf, 1, BUF_SIZE, stdin);
if(pend == p1) {
IOerror = 1;
return -1;
}
}
return *p1++;
}
inline bool blank(char ch) {
return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
}
inline void read(int &x) {
char ch;
while(blank(ch = nc()));
if(IOerror) return;
for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');
}
#undef BUF_SIZE
};
using namespace fastIO;
int max(int x, int y){
return x > y ? x : y;
}
int min(int x, int y){
return x < y ? x : y;
}
int func(int x, int y, int s){
int l = 1, r = s, mid = (l+r)/2, ans = 1;
while(r >= l){
mid = (l+r)/2;
if((sum[x][y]-sum[x-mid][y]-sum[x][y-mid]+sum[x-mid][y-mid] <= 1) ) l = mid+1, ans = mid;
else r = mid-1;
}
return ans;
}
int main()
{
int t, n, m;
read(t);
while(t--){
read(n);
read(m);
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
read(a[i][j]);
// scan_d(a[i][j]);
// scanf("%d", &a[i][j]);
}
}
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
sum[i][j] = sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];
}
}
int ans = 0;
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
int d = min(i, j);
ans = max(ans, func(i, j, d));
}
}
printf("%d\n", ans);
}
return 0;
}