矩阵取数游戏
题目描述
帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的 n×m 的矩阵,矩阵中的每个元素 a i,j均为非负整数。游戏规则如下:
每次取数时须从每行各取走一个元素,共 n 个。经过 m 次后取完矩阵内所有元素;
每次取走的各个元素只能是该元素所在行的行首或行尾;
每次取数都有一个得分值,为每行取数的得分之和.帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分。
题目思路
看到数据范围为80可知,这题能用n3的解法完成,n3考虑区间dp.
已知要求取数后的最大得分,即sum1 + sum2 + sum3 + … + sum3
而sum又等于(令第i行在第j次的值是mij)m1j + m2j + m3j + m4j + … + mnj
即总数可化简(m11 + m12 + m13 … + m1m) + (m21 + m22 …) + (…)
.其实化简到这里题目就很简单了,就是每一行的最大值之和.对每一行使用区间dp即可求出最后答案.由于最后答案会爆long long,所以可以用__int128(但是博主比较懒,直接用python了)
maxn = 87
dp = [[[-1 for i in range(maxn)] for j in range(maxn)] for k in range(maxn)]
arr = []
def dfs(now, l, r, i):
if dp[now][l][r] != -1 :
return int(dp[now][l][r])
if l == r:
dp[now][l][r] = pow(2, i) * arr[now][l]
return int(dp[now][l][r])
dp[now][l][r] = max(dp[now][l][r], dfs(now, l, r - 1, i + 1) + (arr[now][r] * pow(2, i)), dfs(now, l + 1, r, i + 1) + (arr[now][l] * pow(2, i)))
return int(dp[now][l][r])
if __name__ == "__main__":
n, m = map(int, input().split())
for i in range(n):
arr.append(list(map(int, input().split())))
ans = 0
for i in range(n):
ans += dfs(i, 0, m - 1, 1)
print(ans)