法1 贪心+二分 前缀和
#include <bits/stdc++.h>
using namespace std;
int n, m, ans = 0, x, f[205][205];
int main() {
///<ans必然成立
scanf("%d%d", &n, &m);
for (int i=0; i<n; ++i)
for (int j=0; j<m; ++j) {
scanf("%d", &x);
f[i][j]= f[i-1][j]+f[i][j-1]-f[i-1][j-1]+x;//上方 左方 减去重复的左上方,再加上右下角本身
}
for (int i=0; i<n; ++i)
for (int j=0; j<m; ++j) {
int l = 0, r = min(n,m);
while (l<=r) {
int mid = (l+r)>>1;
//如果满足条件,且是小的 那么更新r
if (i+mid>n || j+mid>m || f[i+mid][j+mid]-f[i+mid][j]-f[i][j+mid]+f[i][j] < mid*mid) r = mid-1;
else l = mid+1;
if (f[i+r][j+r]-f[i+r][j]-f[i][j+r]+f[i][j] == r*r) ans = max(ans, r);
}
//
if (f[i+r][j+r]-f[i+r][j]-f[i][j+r]+f[i][j] == r*r) ans = max(ans, r);
}
cout << ans;
return 0;
}
方法二搜索
判断如果是一个·正方形就往下延伸,再让ans++,在选取最大的ans即可
#include<bits/stdc++.h>
using namespace std;
bool a[105][105]={0};
int n,m,ans,xx,yy,maxn;
int dfs(int x,int y){
// if(!a[x+1][y+1])//多余
// return 0;
for(int i=xx;i<=x;i++)//检测正方形的左边
if(!a[i][y])
return 0;
for(int j=yy;j<=y;j++)//检测正方形的下面
if(!a[x][j])
return 0;
ans++;//让ans++并更新新的正方形
dfs(x+1,y+1);
return ans;//若反回此处则返回ans
}
int main(){
//freopen("1387.in ","r",stdin);
//freopen("1387.out","w",stdout);
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)//离线输入
cin>>a[i][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)//枚举每个点
if(a[i][j]){//枚举左上角的点
xx=i;//记录起始点的位置
yy=j;
ans=0;//清空ans
maxn=max(maxn,dfs(i,j));//求出dfs(i,j)的最大值
}
cout<<maxn;
return 0;
}