矩阵取数游戏(区间DP + int128)

原题链接
https://ac.nowcoder.com/acm/problem/16645

思路
考虑后发现每一行独立,可以每一行单独算最大值,最后加起来即可,f[l][r]表示考虑第i行的l到r这个区间,能取到的最大值,这里可以记忆化搜索。转移方程为:f[l][r] = max(f[l + 1][r] + a[l] * x, f[l][r - 1] + a[r] * x),其中x是2^i。注意要用int128

int128读写模板

INT read()
{
    INT x = 0, f = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-') f = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        x = (x << 1) + (x << 3) + c - '0';
        c = getchar();
    }
    return f * x;
}

void print(INT x)
{
    if (x < 0) {
        putchar('-');
        x = -x;
    }
    if (x / 10) print(x / 10);
    putchar(x % 10 + '0');
}

题目代码

#include <bits/stdc++.h>

using namespace std;

#define INT __int128

const int N = 100;

INT a[N];
INT f[N][N];
INT n, m;

INT read()
{
    INT x = 0, f = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-') f = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        x = (x << 1) + (x << 3) + c - '0';
        c = getchar();
    }
    return f * x;
}

void print(INT x)
{
    if (x < 0) {
        putchar('-');
        x = -x;
    }
    if (x / 10) print(x / 10);
    putchar(x % 10 + '0');
}

INT dfs(int l, int r) {
    if (f[l][r]) return f[l][r];
    INT x = (INT)1 << (m - r + l);
    if (l == r) return a[l] * x;
    f[l][r] = max(dfs(l + 1, r) + a[l] * x, dfs(l, r - 1) + a[r] * x);
    return f[l][r];
}

int main() {
    INT ans = 0;
    n = read(), m = read();
    for (int i = 1; i <= n; i ++ ) {
        memset(f, 0, sizeof f);
        
        for (int j = 1; j <= m; j ++ ) a[j] = read();
        ans += dfs(1, m);
    }
    
    print(ans);
    puts("");
    
    return 0;
}
posted on 2021-05-18 21:20  Laurance  阅读(84)  评论(0编辑  收藏  举报