https://nanti.jisuanke.com/t/26015
有一款双人游戏,游戏的地图是一张 n \times mn×m的平面,其中玩家 A 从地图的左上角出发,通过向右和向下走的方式走到右下角,玩家 B 从右上角出发,通过向左和向下的方式走到左下角(每次只能走到上下左右相邻的至多四个格子)。
每个格子有一个分数,玩家走到格子上就会获得这个分数,当一个玩家得到这个分数后,格子的分数就会自动变为 00。游戏最后的得分是两个人获得分数的总和。
即使两个人同时进入一个格子,这个格子上的分数也只会被计入一次。
现在希望你帮忙计算出,这个游戏能获得的最高分是多少。
输入格式
输入第一行一个整数 TT。表示测试数据组数。
接下来输入 TT 组数据。每组数据按照下面的规则输入。
对于每组数据第一行输入两个整数 nn,mm,代表游戏地图的长和宽。
然后接下来的 nn 行每行输入 mm 个整数,代表地图上每个格子的分数。
1 \le T \le 151≤T≤15,3 \le n,m \le 10003≤n,m≤1000。
每个格子分数绝对值 \le 1000≤1000。
输出格式
对于第i
组数据,输出格式形如"Case #i: x"
(输出不含引号),其中x
表示该组数据对应的游戏最高分。
题解:
重合的部分一定是连续的一行几个,或连续的一列几个。
前缀和优化一下就行了。
#include <bits/stdc++.h>
#ifdef LOCAL
#define debug(x) cout<<#x<<" = "<<(x)<<endl;
#else
#define debug(x) 1;
#endif
#define chmax(x,y) x=max(x,y)
#define chmin(x,y) x=min(x,y)
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
#define lowbit(x) x&-x
#define mp make_pair
#define pb push_back
#define fir first
#define sec second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int MOD = 1e9 + 7;
const double PI = acos (-1.);
const double eps = 1e-10;
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3f;
const int MAXN = 5e5 + 5;
int a[1111][1111];
int d1[1111][1111][2]; // 0 上 1 左
int d2[1111][1111][2]; // 0 上 1 右
int d3[1111][1111][2]; // 0 下 1 右
int d4[1111][1111][2]; // 0 下 1 左
int pre1[1111][1111], pre2[1111][1111];
int maxn[1111];
int main() {
#ifdef LOCAL
freopen ("input.txt", "r", stdin);
#endif
int T, cas = 1;
cin >> T;
while (T--) {
int n, m;
scanf ("%d %d", &n, &m);
for (int i = 0; i <= n + 1; i++)
for (int j = 0; j <= m + 1; j++)
for (int k = 0; k < 2; k++) {
d1[i][j][k] = d2[i][j][k] = d3[i][j][k] = d4[i][j][k] = -INF;
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) scanf ("%d", &a[i][j]);
d1[1][1][0] = d1[1][1][1] = a[1][1];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
chmax (d1[i][j][0], max(d1[i - 1][j][0], d1[i - 1][j][1]) + a[i][j]);
chmax (d1[i][j][1], max(d1[i][j - 1][0], d1[i][j - 1][1]) + a[i][j]);
}
}
d2[1][m][0] = d2[1][m][1] = a[1][m];
for (int i = 1; i <= n; i++) {
for (int j = m; j >= 1; j--) {
chmax (d2[i][j][0], max(d2[i - 1][j][0], d2[i - 1][j][1])+ a[i][j]);
chmax (d2[i][j][1], max(d2[i][j + 1][0], d2[i][j + 1][1])+ a[i][j]);
}
}
d3[n][m][0] = d3[n][m][1] = a[n][m];
for (int i = n; i >= 1; i--) {
for (int j = m; j >= 1; j--) {
chmax (d3[i][j][0], max(d3[i + 1][j][0], d3[i + 1][j][1])+ a[i][j]);
chmax (d3[i][j][1], max(d3[i][j + 1][0], d3[i][j + 1][1])+ a[i][j]);
}
}
d4[n][1][0] = d4[n][1][1] = a[n][1];
for (int i = n; i >= 1; i--) {
for (int j = 1; j <= m; j++) {
chmax (d4[i][j][0], max(d4[i + 1][j][0], d4[i + 1][j][1])+ a[i][j]);
chmax (d4[i][j][1], max(d4[i][j - 1][0], d4[i][j - 1][1])+ a[i][j]);
}
}
// debug(d2[2][3][1])
int ans = -INF;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) pre1[i][j] = pre1[i][j - 1] + a[i][j];
for (int j = 1; j <= m; j++)
for (int i = 1; i <= n; i++) pre2[i][j] = pre2[i - 1][j] + a[i][j];
for (int i = 1; i <= n; i++) {
maxn[m + 1] = -INF;
for (int j = m; j >= 1; j--) {
maxn[j] = maxn[j + 1];
for (int k = 0; k < 2; k++)
for (int l = 0; l < 2; l++)
if (k != 1 || l != 1)
chmax(ans, maxn[j] + d1[i][j][k] + d4[i][j][l] - a[i][j] * 2 - pre1[i][j - 1]);
for (int k = 0; k < 2; k++)
for (int l = 0; l < 2; l++)
if (k != 1 || l != 1)
chmax (maxn[j], d2[i][j][k] + d3[i][j][l] - a[i][j] * 2 + pre1[i][j]);
chmax (ans, d1[i][j][0] + d3[i][j][0] + d2[i][j][1] + d4[i][j][1] - a[i][j] * 3);
chmax (ans, d1[i][j][1] + d3[i][j][1] + d2[i][j][0] + d4[i][j][0] - a[i][j] * 3);
// debug(ans)
}
}
for (int j = 1; j <= m; j++) {
maxn[n + 1] = -INF;
for (int i = n; i >= 1; i--) {
maxn[i] = maxn[i + 1];
for (int k = 0; k < 2; k++)
for (int l = 0; l < 2; l++)
if (k != 0 || l != 0)
chmax(ans, maxn[i] + d1[i][j][k] + d2[i][j][l] - a[i][j] * 2 - pre2[i - 1][j]);
for (int k = 0; k < 2; k++)
for (int l = 0; l < 2; l++)
if (k != 0 || l != 0)
chmax (maxn[i], d4[i][j][k] + d3[i][j][l] - a[i][j] * 2 + pre2[i][j]);
}
}
printf ("Case #%d: %d\n", cas++, ans);
}
return 0;
}