P题1351-1399
P1387 最大正方形
题目描述
在一个 $n\times m$ 的只包含 $0$ 和 $1$ 的矩阵里找出一个不包含 $0$ 的最大正方形,输出边长。
输入格式
输入文件第一行为两个整数 $n,m(1\leq n,m\leq 100)$,接下来 $n$ 行,每行 $m$ 个数字,用空格隔开,$0$ 或 $1$。
输出格式
一个整数,最大正方形的边长。
样例 #1
样例输入 #1
4 4
0 1 1 1
1 1 1 0
0 1 1 0
1 1 0 1
样例输出 #1
2
直接暴力枚举
#include <iostream>
#include <algorithm>
using namespace std;
using ll = long long;
using ull = unsigned long long;
const ull N = 1e3 + 100;
const ull M = 1e3 + 200;
ull a[N][M];
ull prefix[N][M];
ull diff[N][M];
int main()
{
int n, m;
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)
{
prefix[i][j] = prefix[i - 1][j] + prefix[i][j - 1] - prefix[i - 1][j - 1] + a[i][j];
}
}
//暴力枚举?//滑动窗口问题
int minwidows = min(n, m);
while (minwidows > 1)
{
for (int i = 1; i+minwidows-1 <= n; ++i)
{
for (int j = 1; j+minwidows-1 <= m; ++j)
{
ll tmp = prefix[i + minwidows - 1][j + minwidows - 1] - prefix[i - 1][j + minwidows - 1] - prefix[i + minwidows - 1][j - 1] + prefix[i - 1][j - 1];
if (tmp == minwidows * minwidows)
{
cout << minwidows << '\n';
return 0;
}
}
}
minwidows--;
}
cout << minwidows << '\n';
return 0;
}
或者使用dp来做
#include <iostream>
#include <vector>
#include <map>
#include <numeric>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
const int MAX = 1e3 + 100;
ll a[MAX][MAX];
ll dp[MAX][MAX];
ll prefix[MAX][MAX];
ll ans;
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= m; ++j)
{
cin >> a[i][j];
}
}
//dp 状态转移方程为 dp[i][j]=min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1])+1;
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= m; ++j)
{ if (a[i][j] == 1)
{
dp[i][j] = min(min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
ans = max(dp[i][j], ans);
}
}
}
cout << ans << "\n";
return 0;
}