P1005 [NOIP2007 提高组] 矩阵取数游戏(区间dp)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1005 [NOIP2007 提高组] 矩阵取数游戏(区间dp)相关的知识,希望对你有一定的参考价值。

P1005 [NOIP2007 提高组] 矩阵取数游戏(区间dp)

  • 每行相互独立

  • 满足重叠子问题,所以解决一行,然后求和即可。

  • 注意到每次只能取两端,对于某一行利用区间dp求解即可。

    d p [ i ] [ j ] = m a x ( d p [ i + 1 ] [ j ] + a [ i ] × 2 m − ( j − i + 1 ) + 1 , d p [ i ] [ j − 1 ] + a [ j ] × 2 m − ( j − i + 1 ) + 1 ) dp[i][j]=max(dp[i+1][j]+a[i]\\times 2^{m-(j-i+1)+1},dp[i][j-1]+a[j]\\times 2^{m-(j-i+1)+1}) dp[i][j]=max(dp[i+1][j]+a[i]×2m(ji+1)+1,dp[i][j1]+a[j]×2m(ji+1)+1)

注意会溢出,用__int128或高精度。

时间复杂度: O ( n m 2 ) O(nm^2) O(nm2)

python

if __name__ == '__main__':
    n, m = map(int, input().split())
    ans, x = 0, 2
    w = [1]
    for i in range(m):
        w.append(x)
        x <<= 1
    for k in range(n):
        a = [0]
        a.extend(list(map(int, input().split())))
        f = [[0 for i in range(m + 5)] for j in range(m + 5)]
        for i in range(m):
            j = 1
            while i + j <= m:
                f[j][i + j] = max(f[j + 1][i + j] + a[j] * w[m-i], f[j][i + j - 1] + a[i + j] * w[m-i])
                j += 1
        ans += f[1][m]
    print(ans)

c++(参考题解)

// Problem: P1005 [NOIP2007 提高组] 矩阵取数游戏
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1005
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// Date: 2021-05-20 20:14:11
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
const int N=100;
int n,m;
__int128 a[N][N],f[N][N];
template<class T>
inline void read(T &x){ 
	x=0;int w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
	for(;ch>='0'&&ch<='9';ch=getchar())
		x=(x<<3)+(x<<1)+(ch&15);
	x*=w; 
}
inline void write(__int128 x){
    if(x<0){
        putchar('-');
        x=-x;
    }
    if(x>9)
        write(x/10);
    putchar(x%10+'0');
}
__int128 dp(__int128 sum[])
{
	memset(f,0,sizeof(f));
	int i,j;
	for(i=0;i<m;i++)
		for(j=1;i+j<=m;j++)
			f[j][i+j]=max(2*(f[j+1][i+j]+sum[j]),2*(f[j][i+j-1]+sum[i+j]));
	return f[1][m];
}
int main()
{
	read(n),read(m);
	int i,j;
	for(i=1;i<=n;i++)
		for(j=1;j<=m;j++)
			read(a[i][j]);
	__int128 ans=0;
	for(i=1;i<=n;i++)
		ans+=dp(a[i]);
	write(ans);
	return 0;
}

以上是关于P1005 [NOIP2007 提高组] 矩阵取数游戏(区间dp)的主要内容,如果未能解决你的问题,请参考以下文章

dp+高精度(洛谷1005 矩阵取数游戏NOIP 2007 提高第三题)

NOIP2007矩阵取数

矩阵取数游戏 NOIP 2007

P1005 矩阵取数游戏

NOIp2007 矩阵取数游戏

洛谷P1005 矩阵取数游戏