传纸条
这题一眼看就是 DP。考虑如何建状态。
首先,我们可以把问题转化为从 (1,1) 出发,选择到 (n,n) 的两个路径,使这两个路径中途没有交点。
有一个显然的性质:从 (1,1) 出发,走到 (x,y) 需要 (x−1)+(y−1) 步。在这道题里,只要同一时刻,两个点的纵坐标不相等,则这两个路径没有交点。那么我们可以定义 fs,i,j 表示:纵、横坐标和为 s,左边那个点的纵坐标为 i,右边那个点的纵坐标为 j 的最大和。
fs,i,j=max{fs−1,i,j,fs−1,i−1,j,fs−1,i,j−1,fs−1,i−1,j−1}+as−i,i+as−j,j
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| #include <bits/stdc++.h>
using namespace std;
int n, m; int a[55][55], f[105][55][55];
int main() { cin >> n >> m; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { cin >> a[i][j]; } } memset(f, -1, sizeof(f)); f[2][1][1] = 0; for (int s = 3; s < n + m; ++s) { for (int i = 1; i < m; ++i) { for (int j = i + 1; j <= m; ++j) { if (s - i > n || s - j > n) continue ; int tmp = -1; tmp = max(tmp, f[s - 1][i][j]); tmp = max(tmp, f[s - 1][i - 1][j]); tmp = max(tmp, f[s - 1][i][j - 1]); tmp = max(tmp, f[s - 1][i - 1][j - 1]); if (tmp == -1) continue ; f[s][i][j] = tmp + a[s - i][i] + a[s - j][j]; } } } cout << f[n + m - 1][m - 1][m] << endl; return 0; }
|