题目大意:给定一个有坏点的矩阵,求能画出来的最大的“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; } //あぁ 花火が夜空 綺麗に咲いて ちょっと切なく // あぁ 風が時間と ともに流れる
时间: 2024-10-19 04:32:52