【Hihocoder1634】Puzzle Game(DP)

题意:有一个n*m的矩阵,每个矩阵里有一个数字a[i][j]。现在要求将其中一个格子的值改为p,使得修改后矩阵的最大子矩阵和最小,求这个最小值

n,m<=150,abs(a[i][j])<=1e3

思路:学习cf,也把这种题叫DP了……

考虑如何快速求出修改后最大子矩阵的值

最大子矩阵有一个O(n^3)的写法:枚举所处的两行或两列,剩下的就当做最大子串做

用这样的方法预处理出上下左右四个方向的最大子矩阵之后,枚举任意一个原最大子矩阵中每个点是否修改

如果有多个最大子矩阵除非枚举到重叠部分否则答案不会改变

枚举后的答案即为原最大子矩阵的值修改后的值与上下左右四个方向的max取max

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 #include<cmath>
  6 #include<bitset>
  7 typedef long long ll;
  8 using namespace std;
  9 #define N   160
 10 #define oo  10000000
 11 #define MOD 100000073
 12 
 13 int s[N][N],a[N][N],U[N],D[N],L[N],R[N];
 14 
 15 int calc(int x1,int y1,int x2,int y2)
 16 {
 17     return s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1];
 18 }
 19 
 20 int main()
 21 { 
 22     //freopen("hihocoder1634.in","r",stdin);
 23     //freopen("hihocoder1634.out","w",stdout); 
 24     int n,m,p;
 25     while(scanf("%d%d%d",&n,&m,&p)!=EOF)
 26     {
 27         for(int i=1;i<=n;i++)
 28          for(int j=1;j<=m;j++) scanf("%d",&a[i][j]);
 29         memset(s,0,sizeof(s));
 30         for(int i=0;i<=n+1;i++) U[i]=D[i]=-oo;
 31         for(int i=0;i<=m+1;i++) L[i]=R[i]=-oo;
 32         for(int i=1;i<=n;i++)
 33          for(int j=1;j<=m;j++) s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];
 34         int ans=-oo;
 35         for(int i=1;i<=n;i++)
 36         { 
 37             int tmp=-oo; 
 38              for(int j=1;j<=i;j++)
 39             {
 40                  int t=0;
 41                  for(int k=1;k<=m;k++) 
 42                  {
 43                      t+=calc(j,k,i,k);
 44                      tmp=max(tmp,t); 
 45                      if(t<0) t=0;
 46                  } 
 47              }
 48              U[i]=max(U[i-1],tmp);
 49              ans=max(ans,U[i]);
 50         }
 51         
 52         for(int i=n;i>=1;i--)
 53         { 
 54             int tmp=-oo; 
 55              for(int j=i;j<=n;j++)
 56             {
 57                  int t=0;
 58                  for(int k=1;k<=m;k++) 
 59                  {
 60                      t+=calc(i,k,j,k);
 61                      tmp=max(tmp,t); 
 62                      if(t<0) t=0;
 63                  } 
 64              }
 65              D[i]=max(D[i+1],tmp);
 66         }
 67         
 68         for(int i=1;i<=m;i++)
 69         {
 70             int tmp=-oo;
 71             for(int j=1;j<=i;j++)
 72             {
 73                 int t=0;
 74                 for(int k=1;k<=n;k++)
 75                 {
 76                     t+=calc(k,j,k,i);
 77                     tmp=max(tmp,t);
 78                     if(t<0) t=0;
 79                 }
 80             }
 81             L[i]=max(L[i-1],tmp);
 82         }
 83         
 84         for(int i=m;i>=1;i--)
 85         {
 86             int tmp=-oo;
 87             for(int j=m;j>=i;j--)
 88             {
 89                 int t=0;
 90                 for(int k=1;k<=n;k++)
 91                 {
 92                     t+=calc(k,i,k,j);
 93                     tmp=max(tmp,t);
 94                     if(t<0) t=0;
 95                 }
 96             }
 97             R[i]=max(R[i+1],tmp);
 98         }
 99         
100         int sx=0,sy=0,ex=0,ey=0;
101         for(int i=1;i<=n;i++)
102          for(int j=i;j<=n;j++)
103          {
104              if(sx) break;
105              int tmp=-oo;
106              int t=0;
107              int st=1;
108              for(int k=1;k<=m;k++)
109             {
110                 t+=calc(i,k,j,k);
111                 tmp=max(tmp,t);
112                 if(tmp==ans)
113                 {
114                     sx=i; ex=j;
115                     sy=st; ey=k;
116                     break;
117                 }
118                 if(t<0)
119                 {
120                     t=0;
121                     st=k+1;
122                 }
123             }    
124         } 
125         //printf("ans=%d
",ans);
126         //printf("%d %d %d %d
",sx,sy,ex,ey);            
127         int cnt=ans; 
128         for(int i=sx;i<=ex;i++)
129          for(int j=sy;j<=ey;j++) cnt=min(cnt,max(ans-a[i][j]+p,max(max(max(U[i-1],D[i+1]),L[j-1]),R[j+1]))); 
130         printf("%d
",cnt);
131     }
132     return 0;
133 }
134     
原文地址:https://www.cnblogs.com/myx12345/p/9996115.html