[Luogu P4147] 玉蟾宫 (网格DP)

Posted GoldenPotato的OI世界

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Luogu P4147] 玉蟾宫 (网格DP)相关的知识,希望对你有一定的参考价值。

题面

传送门:https://www.luogu.org/problemnew/show/P4147

 


Solution

裸的求极大子矩阵

感谢wzj dalao的教学

首先,有一个很显然但很重要的结论,那就是求极大子矩阵肯定要贴着边或一个障碍点,否则就会浪费

 

根据这个定理,我们可以考虑一种做法

我们可以枚举每一个可放置的点

我们可以很轻松的得知它与它左边的障碍点(或边界)的距离,也可以得知它上面与下面能扩展到哪里(即无障碍点最多能到哪里)

那这个点能扩出的长方形的最大面积就是它左边的上面与下面能扩展出来的距离的最小值*它到左边障碍点的距离

如图:

 

[图待补充]

 

然后取一个最大的面积就好

 


Code

 1 //Luogu P4147 玉蟾宫
 2 //May,9th,2018
 3 //悬线法旋转90°求极大子矩阵
 4 #include<iostream>
 5 #include<cstdio>
 6 #include<cstring>
 7 using namespace std;
 8 const int N=1000+10;
 9 const int inf=0x3f3f3f3f;
10 int up[N][N],down[N][N],a[N][N],n,m;
11 int main()
12 {
13     scanf("%d%d",&n,&m);
14     char c[2];
15     memset(a,0x80,sizeof a);
16     for(int i=1;i<=n;i++)
17         for(int j=1;j<=m;j++)
18         {
19             scanf("%s",c+1);
20             if(c[1]==\'F\') 
21                 a[i][j]=0;
22         }
23     
24     for(int i=1;i<=n;i++)
25         for(int j=1;j<=m;j++)
26             if(a[i][j]==0 and a[i-1][j]==0)
27                 up[i][j]=up[i-1][j]+1;
28     for(int i=n;i>=1;i--)
29         for(int j=1;j<=m;j++)
30             if(a[i][j]==0 and a[i+1][j]==0)
31                 down[i][j]=down[i+1][j]+1;
32     
33     int ans=0,u=inf,d=inf,w=0;
34     for(int i=1;i<=n;i++)
35     {
36         u=d=inf;
37         w=0;
38         for(int j=1;j<=m;j++)
39             if(a[i][j]!=0)
40             {
41                 u=d=inf;
42                 w=0;
43             }
44             else
45             {
46                 u=min(u,up[i][j]);
47                 d=min(d,down[i][j]);
48                 ans=max(ans,(++w)*(u+d+1));
49             }
50     }
51     printf("%d",ans*3);
52     return 0;
53 }
正解(C++)

 

以上是关于[Luogu P4147] 玉蟾宫 (网格DP)的主要内容,如果未能解决你的问题,请参考以下文章

P4147 玉蟾宫

Luogu4147 玉蟾宫

[DP专题]悬线法

2491 玉蟾宫

[BZOJ3039]玉蟾宫

codevs 2491 玉蟾宫