中文题
想法:
借dalao的一张图片
这题其实和之前做过的最大正方形差不多
我们同样定义 f[i][j] 代表以(i,j) 为右下角的符合条件的最大正方形
那么我们怎么进行转移,不难发现这个最大正方形的边长取决于 (i,j)左边连续0的数目,(i,j)上边连续0的数目,以及 f[i-1][j-1]
所以我们可以先预处理出左边连续0的数目,右边连续0的数目
同理,对于以f[i][j] 代表以(i,j)为左下角的符合条件的最大正方形也是采取类似的处理方法
#include <algorithm> #include <string> #include <string.h> #include <vector> #include <map> #include <stack> #include <set> #include <queue> #include <math.h> #include <cstdio> #include <iomanip> #include <time.h> #include <bitset> #include <cmath> #include <sstream> #include <iostream> #include <cstring> #define LL long long #define ls nod<<1 #define rs (nod<<1)+1 #define pii pair<int,int> #define mp make_pair #define pb push_back #define INF 0x3f3f3f3f const double eps = 1e-10; const int maxn = 2500 + 10; const LL mod = 1e9 + 7; int sgn(double a){return a < -eps ? -1 : a < eps ? 0 : 1;} using namespace std; int a[maxn][maxn]; int f[maxn][maxn]; int l[maxn][maxn],r[maxn][maxn],u[maxn][maxn]; int main() { ios::sync_with_stdio(false); int n,m; cin >> n >> m; int ans = 0; for (int i = 1;i <= n;i++) { for (int j = 1;j <= m;j++) { cin >> a[i][j]; if (!a[i][j]) { l[i][j] = l[i][j-1] + 1; u[i][j] = u[i-1][j] + 1; } else { f[i][j] = min(f[i-1][j-1],min(l[i][j-1],u[i-1][j])) + 1; } ans = max(ans,f[i][j]); } } for (int i = 1;i <= n;i++) { for (int j = m;j >= 1;j--) { if (!a[i][j]) { r[i][j] = r[i][j+1] + 1; } else { f[i][j] = min(f[i-1][j+1],min(r[i][j+1],u[i-1][j])) + 1; } ans = max(ans,f[i][j]); } } cout << ans << endl; return 0; }