[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 }
自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。