原题链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1424
逐渐找到做这种题的感觉了。
二分法。g[i][j]存储坐标(i, j)的值,s[i][j]存储的值为左上角为起始点(1,1),右下角为(i,
j)的矩形区域内所有值的和,那么:
s[i][j] = g[i][j] + s[i-1][j] + s[i][j-1] - s[i-1][j-1]
扫描整个矩形,遇到为“1”的点就将其作为起点,开始二分边长,利用数组s在O(1)的时间复杂度内判断是否满足为由1组成的正方形,不管更新最大值即可。
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;#define N 1005
int g[N][N], s[N][N];
int n, m;
bool ok(int i, int j, int mid)
{
int t1 = mid * mid;
int t2 = s[i+mid-1][j+mid-1] - s[i+mid-1][j-1] - s[i-1][j+mid-1] + s[i-1][j-1];
return t1 == t2;
}int bs(int i, int j)
{
int l = 1, r = N;
while(l < r)
{
int mid = (l + r) >> 1;
if(i + mid - 1 > m || j + mid - 1 > n)
r = mid;
else if(ok(i, j, mid))
l = mid+1;
else
r = mid;
}
return (l-1) * (l-1);
}int main()
{
int ans;
while(scanf("%d%d", &n, &m) != EOF)
{
for(int i = 1; i <= m; i++)
for(int j = 1; j <= n; j++)
scanf("%d", &g[i][j]);for(int i = 1; i <= m; i++)
for(int j = 1; j <= n; j++)
s[i][j] = g[i][j] + s[i-1][j] + s[i][j-1] - s[i-1][j-1];
ans = 0;
for(int i = 1; i <= m; i++)
for(int j = 1; j <= n; j++)
if(g[i][j])
ans = max(ans, bs(i, j));
printf("%d\n", ans);
}
return 0;
}
View
Code
CSU 1424 Qz’s Maximum All One Square,布布扣,bubuko.com