/* 因为每一秒只能走一个单位长度,而每走一个单位长度又会消耗一个体力值,如果体力值没有了时间还有也只能按照体力值计算,反之一样,所以V对于时间和体力值取小 cnt记录有桃子的树的个数,node[cnt].c表示在第cnt颗树上每次可摘桃子的个数,node[cnt].v表示从起点到第cnt棵树来回的距离,wz[i][j]表示从(0,0)到(i,j)范围内树的个数 node[i]记录第i棵树可以摘的次数 dp方程式为ans[j]=max(ans[j],ans[j-k*node[i].v]+k*node[i].c),不摘第j棵树的第k次与摘了之后获得的桃子取大 */ #include<iostream> #include<cstdio> #include<cstring> using namespace std; #define maxn 1010 struct node{ int v,c,k; }N[maxn*maxn]; int V; int ans[maxn]={0},wz[maxn][maxn]; int cnt=0,n,m,t,a; int main() { scanf("%d%d%d%d",&n,&m,&t,&a); if(t<a-1) V=t;//因为最后要有剩余体力所以此处先减1 else V=a-1; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { int u; scanf("%d",&u); if(u) { N[++cnt].c=u; N[cnt].v=2*(i+j); wz[i][j]=cnt; } } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { int u; scanf("%d",&u); if(u) N[wz[i][j]].k=u; } for(int i=1;i<=cnt;i++) for(int j=V;j>=1;j--) for(int k=1;k<=N[i].k;k++) if(j-k*N[i].v>=0) ans[j]=max(ans[j],ans[j-k*N[i].v]+k*N[i].c); printf("%d",ans[V]); return 0; }