一名苦逼的OIer,想成为ACMer

Iowa_Battleship

洛谷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编辑  收藏  举报

导航