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−(j−i+1)+1,dp[i][j−1]+a[j]×2m−(j−i+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)的主要内容,如果未能解决你的问题,请参考以下文章