zoukankan      html  css  js  c++  java
  • 【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     
  • 相关阅读:
    装饰器模式
    原型模式
    观察者模式
    Apollo 代码的编译演示
    Apollo 框架的剖析1
    gPRC学习笔记
    Docker入门
    ROS入门学习
    Mudo C++网络库第十一章学习笔记
    Mudo C++网络库第十章学习笔记
  • 原文地址:https://www.cnblogs.com/myx12345/p/9996115.html
Copyright © 2011-2022 走看看