Description

帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数。游戏规则如下:
1.每次取数时须从每行各取走一个元素,共n个。m次后取完矩阵所有元素;
2.每次取走的各个元素只能是该元素所在行的行首或行尾;
3.每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分 = 被取走的元素值 * ,其中i表示第i次取数(从1开始编号);
4.游戏结束总得分为m次取数得分之和。
帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分。

Solution

这种题目描述,包含了很多决策状态,肯定是动态规划来做的。由于每一行是独立的,不会相互影响,那么对每一行都取最优决策即可。
我们令 为当前行取[i,j]区间能得到的最优值,显然有递推式
显然有递推式
对每行做上述dp,通过记忆化搜索保证每个状态只访问一次,这里需要使用高精度,跟zzugzx偷学了一手python

Code

while True:
    try:
        n, m = map(int, input().split());
        dp = [[0 for i in range(81)] for i in range(81)]; 
        a = [0 for i in range(n + 1)];
        def solve(l, r):
            p = r - l + 1;
            k = m - p + 1;
            if dp[l][r] :
                return dp[l][r];
            if l == r :
                return a[l] * (2 ** k);
            dp[l][r] = max(solve(l + 1, r) + a[l] * (2 ** k), solve(l, r - 1) + a[r] * (2 ** k));
            return dp[l][r];
        ans = 0;
        for i in range(n):
            dp = [[0 for i in range(100)] for i in range(100)];
            a = list(map(int, input().split()));
            ans += solve(0, m - 1);
        print(ans);
    except EOFError:
        break