题意

一个的矩阵,每次每行取一个数,取次。

每行取数的得分 被取走的元素值

求得分的最大值。

分析

显然每行怎么取值都是相互独立的,不会影响其他行,所以我们只需要考虑如何取值才可以让一行的得分最大化。

很明显,我们最先只可以取第一个或者最后一个数,第二次取剩下的第一个或者最后一个数。

我们可以利用区间dp记忆化来做这题。

注意会爆

#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define pii pair<int,int>
#define int __int128_t
const int inf = 0x3f3f3f3f;
const int maxn = 85;
const int M = 1e9+7;
int n,m,k,ok;

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 a[maxn],b[maxn];

int dp[maxn][maxn][maxn];

int dfs(int l,int r,int cs)         //[l,r]区间取第cs个数
{   
    if(cs > m) return 0;
    if(dp[l][r][cs]) return dp[l][r][cs];
    int ans1 = b[cs]*a[l] + dfs(l+1,r,cs+1);        //取第一个数
    int ans2 = b[cs]*a[r] + dfs(l,r-1,cs+1);        //取最后一个数
    return dp[l][r][cs] = max(ans1,ans2);           //记忆化
}

signed main()
{
    n = read(),m = read();
    int ans = 0;
    b[1] = 2;
    for(int i = 2; i <= m; i++) 
    {
        b[i] = b[i-1]*2;
    }
    for(int i = 1; i <= n; i++) 
    {
        for(int j = 1; j <= m; j++) 
        {
            a[j] = read();
        }
        mem(dp,0);
        ans += dfs(1,m,1);
    }
    print(ans);
    return 0;
}