矩阵取数游戏
- 容易发现每一行是独立的,分别dp
- 设(f(i,j,k))表示当前行,取到第i轮时,前面取了j个数,后面取了k个数,最大得分
#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define SZ(x) ((int)x.size())
#define ALL(x) x.begin(),x.end()
#define U(i,u) for(register int i=head[u];i;i=nxt[i])
#define rep(i,a,b) for(register int i=(a);i<=(b);++i)
#define per(i,a,b) for(register int i=(a);i>=(b);--i)
using namespace std;
typedef __int128 lll;
typedef long double ld;
typedef long long ll;
typedef unsigned int ui;
typedef pair<int,int> PII;
typedef vector<int> VI;
template<class T> inline void read(T &x){
x=0;char c=getchar();int f=1;
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=x*10+c-'0';c=getchar();}x*=f;
}
template<class T> inline void cmin(T &x, T y){x=x<y?x:y;}
template<class T> inline void cmax(T &x, T y){x=x>y?x:y;}
const int N=81;
const int M=81;
lll qpow(lll a,lll b){
lll res=1;
for(;b;b>>=1){
if(b&1)res*=a;
a*=a;
}
return res;
}
void print(lll x){
if(!x)return;
if(x)print(x/10);
putchar(x%10+'0');
}
int n,m;
lll g[N][M],f[M][M][M],ans;
int main(){
read(n);read(m);rep(i,1,n)rep(j,1,m)read(g[i][j]);
rep(t,1,n){
lll tmp=0;memset(f,0,sizeof(f));
rep(i,1,m){
rep(j,0,i){
int k=i-j;
if(j)cmax(f[i][j][k],f[i-1][j-1][k]+g[t][j]*qpow(2,i));
if(k)cmax(f[i][j][k],f[i-1][j][k-1]+g[t][m-k+1]*qpow(2,i));
if(i==m)cmax(tmp,f[i][j][k]);
}
}
ans+=tmp;
}
if(!ans)printf("0");
print(ans);
return 0;
}