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\n",ans);
64     return 0;
65 }
View Code

 

posted @ 2017-10-11 18:59  whymhe  阅读(179)  评论(0编辑  收藏  举报