洛谷 1736 创意吃鱼法
这是一道来自洛谷普及训练场的题目。
第一眼看到此题,觉得一个2维DP加一个2维前缀和就ok了,结果72分。。。卡了很久,最后才明白错误的原因。
int calc(int x, int y, int ex, int ey) //72分 忽略了部分继承的情况 { return s[ex][ey] - s[x - 1][ey] - s[ex][y - 1] + s[x - 1][y - 1]; } int main() { n = read(); m = read(); for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j) { if (j == 1) b = 0; a[i][j] = read(); b += a[i][j]; s[i][j] = s[i - 1][j] + b; } for (int i = 1; i <= m; ++i) if (a[1][i]) dp[1][i][0] = dp[1][i][1] = 1; for (int i = 2; i <= n; ++i) for (int j = 1; j <= m; ++j) { if (a[i][j] == 0) continue; if (dp[i - 1][j - 1][0] && calc(i - dp[i - 1][j - 1][0], j - dp[i - 1][j - 1][0], i, j) == dp[i - 1][j - 1][0] + 1) dp[i][j][0] = dp[i - 1][j - 1][0] + 1; else dp[i][j][0] = 1; if (dp[i - 1][j + 1][1] && calc(i - dp[i - 1][j + 1][1], j, i, j + dp[i - 1][j + 1][1]) == dp[i - 1][j + 1][1] + 1) dp[i][j][1] = dp[i - 1][j + 1][1] + 1; else dp[i][j][1] = 1; ans = max(ans, max(dp[i][j][0], dp[i][j][1])); } cout << ans; }
错误原因是显而易见的,只是我太菜了。。。我们不能只考虑全部继承和全不继承, 我们还要考虑部分继承的情况。
AC代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cctype> using namespace std; int read() { int x = 0; int k = 1; char c = getchar(); while (!isdigit(c)) if (c == '-') c = getchar(), k = -1; else c = getchar(); while (isdigit(c)) x = (x << 1) + (x << 3) + (c ^ 48), c = getchar(); return x * k; } int n, m, ans = 0, b; int a[2505][2505]; int dp[2505][2505]; int l[2505][2505]; int u[2505][2505]; int r[2505][2505]; int main() { n = read(); m = read(); for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j) { a[i][j] = read(); if (!a[i][j]) l[i][j] = l[i][j - 1] + 1, u[i][j] = u[i - 1][j] + 1; else l[i][j] = u[i][j] = 0, dp[i][j] = min(dp[i - 1][j - 1], min(l[i][j - 1], u[i - 1][j])) + 1, ans = max(dp[i][j], ans); } memset(dp, 0, sizeof(0)); 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 r[i][j] = 0, dp[i][j] = min(dp[i - 1][j + 1], min(r[i][j + 1], u[i - 1][j])) + 1, ans = max(dp[i][j], ans); cout << ans; }