洛谷1005 矩阵取数游戏

原题链接

由于每一行之间没有干扰,所以可以一行一行(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;
}
原文地址:https://www.cnblogs.com/Iowa-Battleship/p/9826832.html