题意:
给出n*m的矩阵求最大子矩阵和,要求必须把矩阵中的某一个元素替换成p
代码:
//求最大子矩阵和,容易想到压缩之后dp但是这道题要求必须替换一次p,必然优先替换最小的。 //这样如果求得的结果恰好等于这个矩阵所有的元素的 //和但不是整个矩阵,并且没有替换元素结果就不对了,需要特判一下这种情况。比如以下两组数据: //2 2 -4 2 2 -4 //1 -1 1 1 //1 1 1 1 dp求出来的结果分别是2和4并且没有替换p。 #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int INF=0x3f3f3f3f; int mp[309][309],b[309],c[309],f[309][2]; int n,m,p,ans; void dp() { memset(f,0,sizeof(f)); for(int i=1;i<=m;i++){ f[i][0]=max(f[i-1][0],0)+b[i]; f[i][1]=max(f[i-1][1]+b[i],f[i][0]-c[i]+p); ans=max(ans,max(f[i][0],f[i][1])); } } void solve() { for(int i=1;i<=m;i++){ int sum=0,min_a=INF; for(int j=i;j<=m;j++){ sum+=b[j]; min_a=min(min_a,c[j]); if(i==1&&j==m) ans=max(ans,sum-min_a+p); else ans=max(ans,max(sum,sum-min_a+p)); } } } int main() { //freopen("in.txt","r",stdin); while(scanf("%d%d%d",&n,&m,&p)==3){ for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++) scanf("%d",&mp[i][j]); } ans=-INF; for(int i=1;i<=n;i++){ memset(b,0,sizeof(b)); memset(c,INF,sizeof(c)); for(int j=i;j<=n;j++){ for(int k=1;k<=m;k++){ b[k]+=mp[j][k]; c[k]=min(c[k],mp[j][k]); } if(i==1&&j==n) solve(); else dp(); } } printf("%d ",ans); } return 0; }