区间dp + 高精度
#include<iostream>
#include<cstring>
using namespace std;
const int N = 85,M = 85;
struct node{
string a;
int size;
node operator *(const node &p){
string b = "";
for(int i = 0; i <= p.size + size; i++) b += "0";
for(int i = 0; i <= p.size + size; i++) b[i] -= '0';
for(int i = 1; i <= p.size; i++){
for(int j = 1; j <= size; j++){
b[i + j] += (p.a[i - 1] - '0') * (a[j - 1] - '0');
b[i + j - 1] += b[i + j] / 10;
b[i + j] %= 10;
}
}
for(int i = p.size + size; i >= 1; i--){
b[i - 1] += b[i] / 10;
b[i] %= 10;
}
int sz;
if(b[1] == 0){
sz = p.size + size - 1;
for(int i = 0; i < p.size + size - 1; i++){
b[i] = b[i + 2] + '0';
}
}else{
sz = p.size + size;
for(int i = 0; i < p.size + size; i++){
b[i] = b[i + 1] + '0';
}
}
node cc;
cc.a = b;
cc.size = sz;
return cc;
}
node operator +(const node &p){
string b = "";
int sz = min(p.size,size);
int msz = max(p.size,size) + 1;
for(int i = 0; i < msz; i++) b += "0";
int ans = 0;
for(int i = 0; i < msz; i++){
int x = 0,y = 0;
if(p.size - i - 1 >= 0) x = p.a[p.size - i - 1] - '0';
if(size - i - 1 >= 0) y = a[size - i - 1] - '0';
b[msz - i - 1] = ((x + y + ans) % 10) + '0';
ans = (x + y + ans) / 10;
}
if(b[0] == '0'){
msz--;
for(int i = 0; i < msz; i++) b[i] = b[i + 1];
}
node cc;
cc.a = b;
cc.size = msz;
return cc;
}
void operator =(const node &p){
a = p.a;
size = p.size;
}
}a[N][M];
node b[85];
node dp[N][M][M];
node max(node a,node b){
if(a.size > b.size) return a;
if(b.size > a.size) return b;
for(int i = 0; i < a.size; i++){
if(a.a[i] > b.a[i]) return a;
else if(b.a[i] > a.a[i]) return b;
}
return a;
}
int main(){
b[1].a = "2";
b[1].size = 1;
for(int i = 2; i <= 80; i++){
b[i] = b[1] * b[i - 1];
/*for(int j = 0; j < b[i].size; j++)
cout << b[i].a[j];
cout << endl;*/
}
int n,m;
cin >> n >> m;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
cin >> a[i][j].a;
a[i][j].size = a[i][j].a.size();
}
}
node sum;
sum.a = "0";
sum.size = 1;
node maxn;
maxn.a = "0";
maxn.size = 1;
for(int i = 1; i <= n; i++){
maxn.a = "0";
maxn.size = 1;
for(int len = 1; len <= m; len++){
for(int j = 1; j <= m; j++){
if(j + len - 1 > m) break;
int k = j + len - 1;
dp[i][j][k] = max(dp[i][j][k - 1] + a[i][k] * b[m - len + 1],dp[i][j + 1][k] + a[i][j] * b[m - len + 1]);
maxn = max(maxn,dp[i][j][k]);
/*cout <<i << " " << j << " " << len << " ";
for(int d = 0;d < dp[i][j][k].size; d++) cout << dp[i][j][k].a[d];
cout << " ";
for(int d = 0;d < a[i][j].size; d++) cout << a[i][k].a[d];
cout << " ";
for(int d = 0;d < b[n - len + 1].size; d++) cout << b[m - len + 1].a[d];
cout << endl;*/
}
}
sum = sum + maxn;
}
for(int i = 0; i < sum.size; i++) cout << sum.a[i];
return 0;
}