原题链接
由于每一行之间没有干扰,所以可以一行一行(DP)过去。
设(f[i][j])表示区间([1,i)cup (j, m])被取所取得的最大值,则有转移方程:
(qquadqquad f[i][j] = max{f[i][j], max{f[i - 1][j] + 2^{m - (j - i + 1)} imes a[i - 1], f[i][j + 1] + 2 ^ {m - (j - i + 1)} imes a[j + 1] } })
则每一行取得的最大值为:
(qquadqquad maxlimits_{i = 1} ^ m { f[i][i] + 2 ^ m imes a[i] })
因为数据大,需要使用高精(懒得话可以使用(int128))。
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int N = 85;
const int base = 1e8;
int a[N];
struct bigint {
ll s[N];
int l;
bigint()
{
memset(s, 0, sizeof(s));
l = 0;
}
bigint operator = (const int &b)
{
bigint c;
int x = b;
do
{
c.s[++c.l] = x % base;
x /= base;
} while (x > 0);
return *this = c;
}
bigint operator + (const bigint &b)
{
bigint c;
ll x = 0;
int i, k = l < b.l ? b.l : l;
c.l = k;
for (i = 1; i <= k; i++)
{
x += s[i] + b.s[i];
c.s[i] = x % base;
x /= base;
}
if (x > 0)
c.s[++c.l] = x;
return c;
}
bigint operator * (const int &b)
{
bigint c;
ll x = 0;
int i;
c.l = l;
for (i = 1; i <= l; i++)
{
x += s[i] * b;
c.s[i] = x % base;
x /= base;
}
if (x > 0)
c.s[++c.l] = x;
return c;
}
bool operator < (const bigint &b) const
{
if (l ^ b.l)
return l < b.l;
for (int i = l; i; i--)
if (s[i] < b.s[i])
return true;
else
if (s[i] > b.s[i])
return false;
return false;
}
};
bigint f[N][N], po[N], s, ma;
inline int re()
{
int x = 0;
char c = getchar();
bool p = 0;
for (; c < '0' || c > '9'; c = getchar())
p |= c == '-';
for (; c >= '0' && c <= '9'; c = getchar())
x = x * 10 + c - '0';
return p ? -x : x;
}
inline bigint maxn(bigint x, bigint y)
{
return x < y ? y : x;
}
int main()
{
int i, j, n, m;
n = re();
m = re();
s = 0;
for (po[0] = i = 1; i <= m; i++)
po[i] = po[i - 1] * 2;
while (n--)
{
ma = 0;
for (i = 1; i <= m; i++)
for (j = 1; j <= m; j++)
f[i][j] = 0;
for (i = 1; i <= m; i++)
a[i] = re();
for (i = 1; i <= m; i++)
for (j = m; j >= i; j--)
f[i][j] = maxn(f[i][j], maxn(f[i - 1][j] + po[m - j + i - 1] * a[i - 1], f[i][j + 1] + po[m - j + i - 1] * a[j + 1]));
for (i = 1; i <= m; i++)
ma = maxn(ma, f[i][i] + po[m] * a[i]);
s = s + ma;
}
printf("%lld", s.s[s.l]);
for (i = s.l - 1; i; i--)
printf("%08lld", s.s[i]);
return 0;
}