洛谷1005 矩阵取数游戏
原题链接
由于每一行之间没有干扰,所以可以一行一行\(DP\)过去。
设\(f[i][j]\)表示区间\([1,i)\cup (j, m]\)被取所取得的最大值,则有转移方程:
\(\qquad\qquad f[i][j] = \max\{f[i][j], \max\{f[i - 1][j] + 2^{m - (j - i + 1)} \times a[i - 1], f[i][j + 1] + 2 ^ {m - (j - i + 1)} \times a[j + 1] \} \}\)
则每一行取得的最大值为:
\(\qquad\qquad \max\limits_{i = 1} ^ m \{ f[i][i] + 2 ^ m \times 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;
}
posted on 2018-10-21 21:01 Iowa_Battleship 阅读(124) 评论(0) 编辑 收藏 举报