题目:https://cn.vjudge.net/problem/HihoCoder-1634
题意:给你一个矩阵,可以修改其中一个值为p,让你求最大子矩阵的最小值
我们可以暴力枚举每个点是否修改
当这个点不在最大矩阵内时,一定是它的上下左右的最大子矩阵大
当这个点在最大矩阵内时,可以直接判断
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<algorithm> #include<vector> #include<queue> #include<stack> #include<map> #include<set> using namespace std; const int N=150+5; const int inf=0x80808080; int L[N],R[N],U[N],D[N]; int a[N][N],dp[N][N],ma[N][N]; int n,m,p; void init() { memset(L,0x80,sizeof(L)); memset(R,0x80,sizeof(R)); memset(U,0x80,sizeof(U)); memset(D,0x80,sizeof(D)); } void solve() { int t; //down memset(dp,0,sizeof(dp)); memset(ma,0x80,sizeof(ma)); t=inf; for(int i=1;i<=n;i++) { for(int l=1;l<=m;l++) { int sum=0; for(int r=l;r<=m;r++) { sum+=a[i][r]; dp[l][r]+=sum; ma[l][r]=max(ma[l][r],dp[l][r]); if (dp[l][r]<0) dp[l][r]=0; t=max(t,ma[l][r]); } } D[i]=t; } //up memset(dp,0,sizeof(dp)); memset(ma,0x80,sizeof(ma)); t=inf; for(int i=n;i>=1;i--) { for(int l=1;l<=m;l++) { int sum=0; for(int r=l;r<=m;r++) { sum+=a[i][r]; dp[l][r]+=sum; ma[l][r]=max(ma[l][r],dp[l][r]); if (dp[l][r]<0) dp[l][r]=0; t=max(t,ma[l][r]); } } U[i]=t; } //right memset(dp,0,sizeof(dp)); memset(ma,0x80,sizeof(ma)); t=inf; for(int i=1;i<=m;i++) { for(int l=1;l<=n;l++) { int sum=0; for(int r=l;r<=n;r++) { sum+=a[r][i]; dp[l][r]+=sum; ma[l][r]=max(ma[l][r],dp[l][r]); if (dp[l][r]<0) dp[l][r]=0; t=max(t,ma[l][r]); } } R[i]=t; } //left memset(dp,0,sizeof(dp)); memset(ma,0x80,sizeof(ma)); t=inf; for(int i=m;i>=1;i--) { for(int l=1;l<=n;l++) { int sum=0; for(int r=l;r<=n;r++) { sum+=a[r][i]; dp[l][r]+=sum; ma[l][r]=max(ma[l][r],dp[l][r]); if (dp[l][r]<0) dp[l][r]=0; t=max(t,ma[l][r]); } } L[i]=t; } } int main() { while(scanf("%d%d%d",&n,&m,&p)!=EOF) { init(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&a[i][j]); solve(); int ans=D[n]; /* 为什么可以枚举所有点 因为如果这个点不在最大矩阵内, 当D[n]-a[i][j]+p变大时,不影响ans 当D[n]-a[i][j]+p变小时,不影响t */ for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { int t=max(max(D[i-1],U[i+1]),max(L[j+1],R[j-1])); t=max(t,D[n]-a[i][j]+p); ans=min(ans,t); } printf("%d\n",ans); } return 0; }