P1005 [NOIP 2007 提高组] 矩阵取数游戏题解
jinminghao · · 题解
我们可以发现,这个矩阵的每行都是独立的,于是我们可以分别计算每一行的最大得分。
考虑区间 DP。
对于每一行,我们设
因为每次只能取行首或行尾,所以我们可以推出状态转移方程:
总时间复杂度:
要注意本题需要开__int128。
代码:
#include<cstdio>
#define max(a,b) (a>b?a:b)
using namespace std;
const int N=90,mod=2,mod10=10;
__int128 f[N][N],v[N],ans;
__int128 power(__int128 a,__int128 b){
__int128 ans=1;
while(b){
if(b%mod) ans=ans*a;
b/=mod;
a=a*a;
}
return ans;
}
__int128 read(){
__int128 x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=x*10+(c^48);
c=getchar();
}
return x*f;
}
void write(__int128 x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10^48);
}
int main(){
int m,n;//这里的 n 和 m 与原题相反
scanf("%d%d",&m,&n);
while(m--){
for(int i=1;i<=n;i++){
v[i]=read();
f[i][i]=power(2,n)*v[i];
}
for(int len=2;len<=n;len++){
for(int i=1;i+len-1<=n;i++){
int j=i+len-1;
f[i][j]=max(f[i][j-1]+power(2,n-len+1)*v[j],f[i+1][j]+power(2,n-len+1)*v[i]);
}
}
ans+=f[1][n];
}
write(ans);
return 0;
}