P1005 [NOIP2007 提高组] 矩阵取数游戏

发布时间 2023-03-28 19:34:47作者: QAQ啥也不会

思维题:

显然每个行可以互相独立来处理。

贪心和暴力显然都不容易处理这题,所以我们只能考虑dp。

每次只能取最左边和最右边的数,这显然很符合区间dp的特点。

所以我们令dp[i][j]为取[i,j]区间所能获得的最大值

最后的答案便是dp[1][len]的累和

现在想dp[1][len]该如何获得呢?

显然dp[1][len]只能从dp[2][len]或dp[1][len-1]中得到。

但是每次取的是最左边或最右边的数,显然我们是不知道dp[2][len]和dp[1][len-1]的值的

所以这道题要逆这来思考过程。

一开始我们从这序列中任意取一个元素,此时便是dp[i][i]=a[i]

然后显然只能从 i-1或 i+1来取数,这样区间长度为2的dp状态我们也处理好了

接着便是长度为3,4......,len的长度取完

所以对于dp[i][j]的转移方程便是dp[i][j]=max(dp[i+1][j]*2+a[i],dp[i][j-1]*2+a[j])

这道题要求高精度,所以直接python来写就好了

Code:

N=100
dp=[ [ [0]*N for j in range(N) ] for i in range(N)]
a=[ [0] for i in range(N)]


n,m=map(int,input().split())
for i in range(1,n+1):
    a[i]=a[i]+list(map(int,input().split()))

for i in range(1,n+1):
    for j in range(1,m+1):
        dp[i][j][j]=a[i][j]

for line in range(1,n+1):
    for len in range(2,m+1):
        for i in range(1,m+1):
            j=i+len-1
            if(j>m):
                break
            dp[line][i][j]=max(dp[line][i+1][j]*2+a[line][i],dp[line][i][j-1]*2+a[line][j])
ans=0
for i in range(1,n+1):
    ans+=dp[i][1][m]*2
print(ans)