每行的结果独立,对每行分析。
从边缘取数,容易想到区间DP,f[i][j]表示取完数后剩下[i,j]区间的数未取,此时的最优值,状态转移也十分好想。
高精度,用__int128处理(不想手打高精。。。),注意要手写输入输出(类似快读快写,不能用cin,cout)。
#include <bits/stdc++.h>
using namespace std;
const int N = 100;
int n, m;
__int128 f[N][N], a[N][N], d[N];
__int128 ksm(__int128 a, __int128 b) {
__int128 res = 1;
for (; b; b >>= 1) {
if (b & 1) res *= a;
a *= a;
}
return res;
}
__int128 read() {
__int128 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 * 10 + c - '0';
c = getchar();
}
return x* f;
}
void write(__int128 x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
int main() {
cin >> n >> m;
for (int i = 1; i <= m; i ++) d[i] = ksm(2, i);
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= m; j ++) a[i][j] = read();
__int128 ans = 0;
for (int k = 1; k <= n; k ++) {
memset(f, 0, sizeof(f));
for (int i = 1; i <= m; i ++) {
for (int j = m; j >= i; j --) {
f[i][j] = max(f[i][j], f[i - 1][j] + d[m - j + i - 1] * a[k][i - 1]);
f[i][j] = max(f[i][j], f[i][j + 1] + d[m - j + i - 1] * a[k][j + 1]);
}
}
__int128 mx = 0;
for (int i = 1; i <= m; i ++)
mx = max(mx, f[i][i] + d[m] * a[k][i]);
ans += mx;
}
write(ans);
}