题目大意:给定一个有坏点的矩阵,求能画出来的最大的“8”字形
“8”字形满足:
*数字8由上下两个矩形构成。
*数字8的上下两个矩形都满足至少有一个单元格在矩形内部。
*数字8顶部的矩形的底边必须为底部矩形顶边的子集。
*数字8只能刻在大理石完美无瑕的部分。
*规定数字8的得分为上矩形和下矩形的面积的乘积,它们希望得分能达到最大。
枚举顶部矩形的底边,可以用上一行的底边O(1)转移得到,然后每行O(n^2)向左右拓展
然后枚举底部矩形的顶边,可以用下一行的顶边O(1)转移得到,顶部矩形的最大面积已求出,O(1)更新答案
最终时间复杂度O(n^3) 小心内存
尼玛考试时无解判挂丢了10分。。。简直。。。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 302
using namespace std;
int n;
long long ans=-1;
char map[M][M];
int sum[M][M];
int f[M][M][M],g[M][M][M];
int Get_Sum(int x1,int y1,int x2,int y2)
{
return sum[x2][y2]+sum[x1-1][y1-1]-sum[x2][y1-1]-sum[x1-1][y2];
}
int main()
{
freopen("eight.in","r",stdin);
freopen("eight.out","w",stdout);
int i,j,k;
cin>>n;
for(i=1;i<=n;i++)
scanf("%s",map[i]+1);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+(map[i][j]=='*');
for(i=1;i<=n-2;i++)
for(j=i+2;j<=n;j++)
{
int last=0;
for(k=1;k<=n;k++)
{
if(map[k][i]=='*'||map[k][j]=='*')
last=0;
if(!Get_Sum(k,i,k,j))
{
if(last)
f[k][i][j]=(k-last-1)*(j-i-1);
else
last=k;
}
}
last=0;
for(k=n;k;k--)
{
if(map[k][i]=='*'||map[k][j]=='*')
last=0;
if(!Get_Sum(k,i,k,j))
{
if(last)
g[k][i][j]=(last-k-1)*(j-i-1);
else
last=k;
}
}
}
for(i=1;i<=n;i++)
{
for(j=1;j<=n-3;j++)
for(k=j+3;k<=n;k++)
{
if(Get_Sum(i,j,i,k))
break;
f[i][j][k]=max(f[i][j][k],f[i][j][k-1]);
}
for(j=n;j>=4;j--)
for(k=j-3;k;k--)
{
if(Get_Sum(i,k,i,j))
break;
f[i][k][j]=max(f[i][k][j],f[i][k+1][j]);
}
}
for(i=3;i<=n-2;i++)
for(j=1;j<=n-2;j++)
for(k=j+2;k<=n;k++)
if(!Get_Sum(i,j,i,k))
ans=max(ans,(long long)f[i][j][k]*g[i][j][k]);
cout<<ans<<endl;
}
//あぁ 花火が夜空 綺麗に咲いて ちょっと切なく
// あぁ 風が時間と ともに流れる