算法1
(DP) $O(n^3)$
通过分析,当我们到达[i,j]点时,以前i行前j列的边长为k的数量=前i行前j-1列的数量+以[i,j]为右下角构成正方形的数量.
设f[i][j]
为前i行前j列构成边长为k的正方形数量,f[i][j]=f[i][j-1]+pan(pan(i-k+1,j-k+1,i,j))
.
这里也可以直接用一个变量代替f[i][j]
。
时间复杂度
O(n^3)
C++ 代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=260;
char g[N][N];
int n;
int s[N][N];
int pan(int x1,int y1,int x2,int y2)
{
if((s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1])==(x2-x1+1)*(y2-y1+1)) return 1;
return 0;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
cin>>g[i][j];
s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+(g[i][j]=='1'?1:0);
}
for(int k=2;k<=n;k++)
{
int sum=0;
for(int i=k;i<=n;i++)
for(int j=k;j<=n;j++)
sum+=pan(i-k+1,j-k+1,i,j);
if(sum)
cout<<k<<" "<<sum<<'\n';
}
return 0;
}