• 2017.10.3 国庆清北 D3T3 解迷游戏


    题目描述

    LYK进了一家古董店,它很想买其中的一幅画。但它带的钱不够买这幅画。

    幸运的是,老板正在研究一个问题,他表示如果LYK能帮他解出这个问题的话,就把这幅画送给它。

    老板有一个n*m的矩阵,他想找一个和最大的子矩阵,这个子矩阵可以由四个参数x,y,x2,y2(1<=x<=x2<=n,1<=y<=y2<=m)来表示,表示一个左上角为(x,y),右下角为(x2,y2)的矩阵。

    为了让游戏更加有趣,老板给了一个常数P,他想将原来这个矩阵中恰好一个数变为P,使得这个矩阵的最大的子矩阵尽可能大。

    老板想知道这个最大值是多少。

    你能帮帮LYK吗?

    输入输出格式

    输入格式:

    第一行三个数n,m,P。

    接下来n行,每行m个数ai,j描述整个矩阵。

    输出格式:

    输出一个数表示答案。

    输入输出样例

    输入样例#1:
    3 3 3
    -100 3 3
    3 -4 3
    3 3 3
    输出样例#1:
    20
    
    样例解释
    改变左上角那个数。

    说明

    对于20%的数据n,m<=10。

    对于40%的数据n,m<=25。

    对于60%的数据n,m<=50。

    对于80%的数据n,m<=100。

    对于100%的数据1<=n,m<=300,|P|,|ai,j|<=1000。

    40分暴力:

     1 /*预处理出二维前缀和,枚举每个矩阵,当前矩阵的元素和tot可以用预处理出来的前缀和算出来,然后找每个矩阵中的最小值minn,如果这个最小值minn小于p,那么就将它改为p,tot=tot-minn+p,否则不改。 Ans=max(ans,tot)
     2 时间复杂度O(n^3*m^3)*/
     3 #include<iostream>
     4 #include<cmath>
     5 #include<cstdio>
     6 #include<cstring>
     7 #include<algorithm>
     8 #include<string>
     9 #define N 65
    10 using namespace std;
    11 
    12 int n,m,p,ans=-999999999,minn,zuixiao[N][N][N][N];
    13 int sum[N][N],num[N][N],tot;
    14 
    15 inline void read(int &num)
    16 {
    17     int f=1;
    18     char c=getchar();
    19     for(;!isdigit(c);c=getchar()){if(c=='-') f=-1;};
    20     for(;isdigit(c);c=getchar()){num=num*10+c-'0';};
    21     num*=f;
    22 }
    23 
    24 inline int _max(int a,int b)
    25 {
    26     return a>b?a:b;
    27 }
    28 
    29 inline int _min(int a,int b)
    30 {
    31     return a<b?a:b;
    32 }
    33 
    34 int main()
    35 {
    36     freopen("puzzle.in","r",stdin);
    37     freopen("puzzle.out","w",stdout);
    38     read(n),read(m),read(p);
    39     for(int i=1;i<=n;i++)
    40     {
    41         for(int j=1;j<=m;j++)
    42         {
    43             read(num[i][j]);
    44         }
    45     }
    46     for(int i=1;i<=n;i++)
    47     {
    48         for(int j=1;j<=m;j++)
    49         {
    50             sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+num[i][j];
    51         }
    52     }
    53     for(int i=1;i<=n;i++)
    54     {
    55         for(int j=1;j<=m;j++)
    56         {
    57             for(int k=i;k<=n;k++)
    58             {
    59                 for(int l=j;l<=m;l++)
    60                 {
    61                     tot=sum[k][l]-sum[i-1][l]-sum[k][j-1]+sum[i-1][j-1];
    62                     minn=999999999;
    63                     for(int a=i;a<=k;a++)
    64                     {
    65                         for(int b=j;b<=l;b++)
    66                         {
    67                             minn=_min(minn,num[a][b]);
    68                         }
    69                     }
    70                     if(minn<p) tot=tot-minn+p;
    71                     ans=_max(ans,tot);
    72                 }
    73             }
    74         }
    75     }
    76     printf("%d",ans);
    77     fclose(stdin);
    78     fclose(stdout);
    79     return 0;
    80 }
    View Code

    正解:

     1 /*
     2 n^2前缀和+n^2预处理矩阵最小值+n^3求解
     3 复杂度 O(n^3)
     4 */
     5 #include<iostream>
     6 #include<cstdio>
     7 #include<cmath>
     8 #include<cstring>
     9 #include<algorithm>
    10 #define N 305
    11 #define INF -999999999
    12 using namespace std;
    13 
    14 int n,m,ans,p;
    15 int a[N][N],b[N],minn[N],dp[N][2],sum[N][N];
    16 
    17 int main()
    18 {
    19     scanf("%d",&n);
    20     ans=INF;
    21     scanf("%d%d",&m,&p);
    22     for(int i=1;i<=n;i++)
    23     {
    24         for(int j=1;j<=m;j++)
    25         {
    26             scanf("%d",&a[i][j]);
    27         }
    28     }
    29     for(int i=1;i<=n;i++)
    30     {
    31         for(int j=1;j<=m;j++)
    32         {
    33             sum[i][j]=sum[i-1][j]+a[i][j];
    34         }
    35     }
    36     for(int i=1;i<=n;i++)
    37     {
    38         for(int j=1;j<=m;j++) minn[j]=a[i][j];
    39         for(int j=i;j<=n;j++)
    40         {
    41             for(int k=1;k<=m;k++) minn[k]=min(minn[k],a[j][k]);
    42             for(int k=1;k<=m;k++) b[k]=sum[j][k]-sum[i-1][k];
    43             dp[0][1]=INF;
    44             for(int k=1;k<=m;k++)
    45             {
    46                 dp[k][0]=max(dp[k-1][0]+b[k],b[k]);
    47                 dp[k][1]=max(max(dp[k-1][1]+b[k],dp[k-1][0]+b[k]-minn[k]+p),b[k]-minn[k]+p);
    48             }
    49             for(int k=1;k<m;k++) ans=max(ans,max(dp[k][0],dp[k][1]));
    50             if(i==1&&j==n)
    51             {
    52                 ans=max(ans,dp[m][1]);
    53                 int sum=0;
    54                 for(int k=m;k>1;k--)
    55                 {
    56                     sum+=b[k];
    57                     ans=max(ans,sum);
    58                 }
    59             }
    60             else ans=max(ans,max(dp[m][0],dp[m][1]));
    61         }
    62     }
    63     printf("%d
    ",ans);
    64     return 0;
    65 }
    View Code
  • 相关阅读:
    【Python进阶】用 Python 统计字数
    【Python进阶】无论API怎么变,SDK都可以根据URL实现完全动态的调用
    【机器学习_吴恩达_笔记】(一)机器学习的动机和应用
    【Python入门总结】
    【Python入门学习】列表生成和函数生成器的方式实现杨辉三角
    【Python入门学习】闭包&装饰器&开放封闭原则
    【Pthon入门学习】利用slice实现str的strip函数,类似C#中的string.trim
    【Pthon入门学习】99乘法表
    【Pthon入门学习】多级菜单小例子
    要素图层范围查询属性arcgis api for js(featuretable根据上篇的优化)原创
  • 原文地址:https://www.cnblogs.com/lovewhy/p/7652371.html
Copyright © 2020-2023  润新知