SenseTime Ace Coder Challenge 暨 商汤在线编程挑战赛 A.双人取数

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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值