P2484 [SDOI2011]打地鼠
模拟赛出这题,我暴力剪枝 $n^6$ 过了。颠覆我认知。
考虑朴素算法。枚举 $r,c$,将所有 $r\times c$ 的矩形减去左上角值,最后判断能不能全消成 $0$。
剪枝 $1$:设 $\sum a_{i,j}=tot$。若 $r\times c\nmid tot$ 则跳过。每次总和减去 $r\times c$,则剪枝正确性显然。
剪枝 $2$:若任何时刻矩阵出现负数则退出。矩阵内数只减不增。
剪枝 $3$:若当前要减去的矩阵左上角为 $0$ 则不进行任何操作。
这样我们可以轻松地通过。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 1e2 + 10;
int n, m, tot, ans = 1145141919810ll;
int a[maxn][maxn];
int b[maxn][maxn];
bool check(int r, int c) {
if (tot % (r * c) != 0) return false;
bool flag = true;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
a[i][j] = b[i][j];
}
}
for (int i = 1; i <= n - r + 1; i++) {
for (int j = 1; j <= m - c + 1; j++) {
int x = a[i][j];
if (!x) continue;
for (int p = i; p < i + r; p++) {
for (int q = j; q < j + c; q++) {
if (a[p][q] - x >= 0) a[p][q] -= x;
else {
flag = false;
break;
}
}
if (!flag) break;
}
if (!flag) break;
}
if (!flag) break;
}
if (!flag) return false;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (a[i][j]) return false;
}
}
return true;
}
signed main() {
// freopen("shrew.in", "r", stdin);
// freopen("shrew.out", "w", stdout);
cin >> n >> m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> b[i][j];
tot += b[i][j];
}
}
for (int r = 1; r <= n; r++) {
for (int c = 1; c <= m; c++) {
if (!check(r, c)) continue;
ans = min(ans, tot / (r * c));
}
}
cout << ans;
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 趁着过年的时候手搓了一个低代码框架
· 用 C# 插值字符串处理器写一个 sscanf
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!