传送门:https://hihocoder.com/problemset/problem/1634
题意:给你一个n*m(n,m<=150)的数字矩阵,每个元素val(-1000<=val<=1000),以及一个数字p(-1000<=p<=1000)。你现在最多可以修改矩阵中的一个数字,改成p,求最大子矩阵的最小值
思路:其实关键还是想到,对于某个点(i,j),要么最大子矩阵(设值为ma)经过了这个点,要么没有经过这个点。如果没有经过这个点,我们只需要统计其上下左右四个部分包含的最大子矩阵,记为tmp1,如果经过这个点,就将这个点替换为p,取tmp=max(tmp1,ma-a[i][j]+p)。
最后发现每个点我们都可以同时看成经过和没被经过这样取,因为不会影响最后的答案。最后取ans=min(ans,tmp)。
四个部分的求最大子矩阵时一定要想清楚每一重for的含义。。。
代码:
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define mst(head,x,n) memset(head+1,x,n*sizeof(head[0]))
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define dep(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
const int maxn=150+5;
const int MAXN=1e7+5;
//const double pi=acos(-1.0);
//const double eps=1e-9;
//const ll mo=1e9+7;
int n,m,k;
int L[maxn],R[maxn],U[maxn],D[maxn];
int a[maxn][maxn],sum[maxn],c[maxn];
int ans,tmp,cnt;
int flag;
template <typename T>
inline void read(T &X){
X=0;int w=0; char ch=0;
while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
if(w) X=-X;
}
int main(){
int T,cas=1;
//read(T);
//while(T--)
while(scanf("%d%d%d",&n,&m,&k)!=EOF)
{
//read(n);read(m);read(k);
rep(i,1,n){
rep(j,1,m) scanf("%d",&a[i][j]);
//read(a[i][j]);
}
rep(i,0,max(n,m)+1)
L[i]=R[i]=U[i]=D[i]=-inf;
rep(i,1,n){
rep(j,1,m) sum[j]=0;
rep(j,i,n){
int tmp=0;
rep(k,1,m){
sum[k]+=a[j][k];
tmp+=sum[k];
U[j]=max(U[j],tmp);
if(tmp<0) tmp=0;
}
}
U[i]=max(U[i],U[i-1]);
}
dep(i,n,1){
rep(j,1,m) sum[j]=0;
dep(j,i,1){
int tmp=0;
rep(k,1,m){
sum[k]+=a[j][k];
tmp+=sum[k];
D[j]=max(D[j],tmp);
if(tmp<0) tmp=0;
}
}
D[i]=max(D[i],D[i+1]);
}
rep(i,1,m){
rep(j,1,n) sum[j]=0;
rep(j,i,m){
int tmp=0;
rep(k,1,n){
sum[k]+=a[k][j];
tmp+=sum[k];
L[j]=max(L[j],tmp);
if(tmp<0) tmp=0;
}
}
L[i]=max(L[i],L[i-1]);
}
dep(i,m,1){
rep(j,1,n) sum[j]=0;
dep(j,i,1){
int tmp=0;
rep(k,1,n){
sum[k]+=a[k][j];
tmp+=sum[k];
R[j]=max(R[j],tmp);
if(tmp<0) tmp=0;
}
}
R[i]=max(R[i],R[i+1]);
}
int ans=U[n];
rep(i,1,n){
rep(j,1,m) {
int tmp=-inf;
tmp=max(U[i-1],D[i+1]);
tmp=max(tmp,max(L[j-1],R[j+1]));
tmp=max(tmp,U[n]-a[i][j]+k);
ans=min(ans,tmp);
}
}
printf("%d\n",ans);
}
return 0;
}