题意
题解
O ( N 2 ) O(N^2) O(N2) 枚举 r , c r,c r,c,判断打地鼠的可行性,更新答案。对于仍存在 t t t 只地鼠的最左上角的点 ( x , y ) (x,y) (x,y),其打击范围是确定的,即打击的矩形区域左上角为 ( x , y ) (x,y) (x,y),打击的次数为 t t t。
那么依次遍历二维区域的点,同时统计各区域已打击的次数即可,朴素的处理复杂度 O ( N 4 ) O(N^4) O(N4),瓶颈在于二维区域的朴素修改;考虑将二维区域修改转换为二维差分,同时计算前缀和,就可以 O ( N 2 ) O(N^2) O(N2) 判断可行性。求解时加入可行性剪枝与最优性剪枝。总时间复杂度 O ( N 4 ) O(N^4) O(N4)。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 105;
int N, M, res, sum, A[maxn][maxn], B[maxn][maxn];
bool judge(int x, int y)
{
if (sum % (x * y) || sum / (x * y) > res)
return 0;
memset(B, 0, sizeof(B));
for (int i = 1; i <= N; ++i)
for (int j = 1; j <= M; ++j)
{
B[i][j] += B[i - 1][j] + B[i][j - 1] - B[i - 1][j - 1];
int t = A[i][j] - B[i][j];
if (t < 0)
return 0;
if (t > 0)
{
if (i + x - 1 > N || j + y - 1 > M)
return 0;
B[i][j] += t, B[i + x][j] -= t, B[i][j + y] -= t, B[i + x][j + y] += t;
}
}
return 1;
}
int main()
{
scanf("%d%d", &N, &M);
for (int i = 1; i <= N; ++i)
for (int j = 1; j <= M; ++j)
scanf("%d", &A[i][j]), sum += A[i][j];
res = sum;
for (int i = N; i; --i)
for (int j = M; j; --j)
if (judge(i, j))
res = min(res, sum / (i * j));
printf("%d\n", res);
return 0;
}