Description
给一个N*N的01矩阵, 求一个面积最大的全为1的正方形子矩阵. 输出它的面积.
Input
输入文件square.in的第一行包含一个正整数N.
接下来N行, 每行N个数, 保证不是0就是1. 每行相邻两个数之间没有空格.
Output
输出文件为square.out,仅包含一个整数表示最大的全1子正方形矩阵的面积。
Hint
[数据规模和约定]
80%的数据中 N<=250;
100%的数据中 N <= 1000。
题解
二分正方形的边长,枚举是1的起始点,查找更新答案
code
#include <stdio.h>
#include <iostream>
using namespace std;
int x[1011001],y[1011001];
int map[1111][1111];
int f[1111][1111];
char c[1111];
int acre(int i,int j,int k)
{
return f[i+k-1][j+k-1]-f[i-1][j+k-1]-f[i+k-1][j-1]+f[i-1][j-1];
}
bool check(int i,int j,int k)
{
return acre(i,j,k)==k*k;
}
int main()
{
int n,ans=0,count=0;
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%s",&c);
for (int j=1;j<=n;j++)
{
map[i][j]=(int)(c[j-1])-48;
if (map[i][j])
{
x[++count]=i;
y[count]=j;
}
}
}
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+map[i][j];
int l=1,r=n;
while (l<=r)
{
int mid=(l+r)/2;
int k=mid;
bool flag=false;
for (int v=1;v<=count;v++)
{
if ((x[v]+k-1<=n)&&(y[v]+k-1<=n)&&check(x[v],y[v],k))
{
flag=true;
if (acre(x[v],y[v],k)>ans)
ans=acre(x[v],y[v],k);
break;
}
}
if (flag)
l=mid+1;
else
r=mid-1;
}
printf("%d\n",ans);
return 0;
}