某大型纪录片(P14169 题解)
Senior_Young · · 题解
这题一看就是动态规划。
我们设
根据题意可以直接写出 DP 式子,具体怎么推出来的不再赘述:
其中
初始条件为 但好像和直接 memset(f,0,sizeof f); 没什么区别。
最终答案是
:::info[什么你还不会求
代码:
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
sum[i][j]=sum[i][j-1]+a[i][j];
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
q[i][j]=sum[i][min(n,j+X)]-sum[i][max(1,j-X)-1];
:::
当然这样的 DP 时间复杂度
我们可以利用七年级知识把原式转换成下面这样:
可以发现,原式的计算主要涉及
两部分。
我们设:
我们发现,
初始条件为
同理我们设:
则也有:
初始条件为:
上述所有的
那
就这样,我们用
好像没有什么问题了吧……于是我们写完了代码,自信一交:
程序在
\text{64MB} 里撞出闷响,数组的影子漫过了内存的墙。记录里的\textcolor{#052242}{\text{MLE}} 像道锁,困住了我高深算法的光。
哦,忘了,空间复杂度也是
不过我们分析了
DP 式就变成了:
当我们把新的代码交上去的那一瞬间,绿色的
我们以
代码:
#include<iostream>
#include<cstring>
using namespace std;
const int N=315;
int f[N][N],a[N][N],q[N][N],sum[N][N],s[N][N],t[N][N];
int n,m,X,T;
int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9') f=(c=='-'?-1:f),c=getchar();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*f;
}
void solve(){
n=read(),m=read(),X=read(),T=read();
memset(f,0,sizeof f);
memset(sum,0,sizeof sum);
memset(q,0,sizeof q);
memset(s,0,sizeof s);
memset(t,0,sizeof t);
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
a[i][j]=read();
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
sum[i][j]=sum[i][j-1]+a[i][j];
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
q[i][j]=sum[i][min(n,j+X)]-sum[i][max(1,j-X)-1];
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++)
for(int k=0;k<=T;k++)
f[j][k]=max(s[j][k],t[j][k])+q[i][j];
for(int j=n;j>=1;j--)//这里一定要倒序枚举!!!
for(int k=0;k<=T;k++){
if(j==n) s[j][k]=f[j][k];
else if(k==0) s[j][k]=f[j][k];
else s[j][k]=max(s[j+1][k-1],f[j][k]);
}
for(int j=1;j<=n;j++)
for(int k=0;k<=T;k++){
if(j==1) t[j][k]=f[j][k];
else if(k==0) t[j][k]=f[j][k];
else t[j][k]=max(t[j-1][k-1],f[j][k]);
}
}
int answ=0;
for(int j=1;j<=n;j++)
for(int k=0;k<=T;k++)
answ=max(answ,f[j][k]);
printf("%d\n",answ);
}
signed main(){
int Csdsl;Csdsl=read();//CeShiDianShuLiang
while(Csdsl--) solve();
return 0;
}