题目大意:
给你一个
N∗M
的
{0,1}
矩阵,然后只有为
0
的地方可以可用,然后要你找出一个最大的
解题思路:
这道题我只想出了
O(N3logN)
的算法在这里我就不再赘述了,网上估计可以找得到,我还是讲一下
O(N3)
的算法吧。
我们用
F[i][l][r]
表示以第
i
行,第
Second:
然后我们令
G[i][l][r]
表示中间矩形以第
i
行,第
那么显然
G[i][l][r]
转移方程为(当第
i
行第
G[i][l][r]=max(G[i−1][l][r]+r,r+max(F[i−1][l][k],k>r))
显然
max(F[i−1][l][k],k>r)
可以再循环中用一个变量记录更新以达到
O(1)
Thrid:
令
H[i][l][r]
表示最下面的矩形以第
i
行,第
那么同
G
的计算类似,
H[i][l][r]=max(H[i−1][l][r]+r,r+max(G[i−1][l][k],k<r))
然后这道题目就解决了。
输出就简单了
AC代码:
说明:本人由于太弱,边看翱犇的代码边学的题解,然后一不小心就写得和翱犇差不多了 QAQ
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
int n,m;
int ch[200][200]={{0}};
short top[200][200][200]={{{0}}};
short F[200][200][200]={{{0}}};
short G[200][200][200]={{{0}}};
short H[200][200][200]={{{0}}};
int area=0;
int ai=0,al=0,ar=0;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&ch[i][j]);
top[i][j][1]=(short)(ch[i][j]^1)*(top[i-1][j][1]+1);
}
for(int i=n;i>=1;i--)
for(int j=m;j>=1;j--)
{
if(ch[i][j]==1) continue;
for(int k=2;k+j-1<=m && ch[i][k+j-1]==0;k++)
{
top[i][j][k]=min(top[i][j][1],top[i][j+1][k-1]);
F[i][j][k]=top[i][j][k]*k;
}
}
for(int i=2;i<=n;i++)
for(int j=m;j>=1;j--)
{
if(ch[i][j]==1) continue;
int k;
for(k=1;k+j-1<=m && ch[i][k+j-1]==0;k++);k--;
int Max=0;
for(int r=m-j+1;r>k;r--)
Max=max((int)F[i-1][j][r],Max);
for(int r=k;r>=1;r--)
{
if(G[i-1][j][r]>0) G[i][j][r]=G[i-1][j][r]+r;
if(Max>0) G[i][j][r]=max((short)(Max+r),G[i][j][r]);
Max=max((int)F[i-1][j][r],Max);
}
}
for(int i=2;i<=n;i++)
for(int j=m;j>=1;j--)
{
if(ch[i][j]==1) continue;
int Max=0;
for(int k=1;k+j-1<=m && ch[i][k+j-1]==0;k++)
{
H[i][j][k]=max((H[i-1][j][k]>0)*(H[i-1][j][k]+k),(Max>0)*(Max+k));
Max=max((int)G[i-1][j][k],Max);
if(H[i][j][k]>area)
{
area=H[i][j][k];
ai=i,al=j,ar=k;
}
}
}
if(area<5) cout<<-1<<endl;
else
{
cout<<area<<endl;
for(;H[ai-1][al][ar]+ar==H[ai][al][ar];ai--)
for(int i=1;i<=ar;i++)
ch[ai][al+i-1]=8;
for(int r=1;r<=ar;r++)
if(G[ai-1][al][r]+ar==H[ai][al][ar])
{
for(int k=1;k<=ar;k++)
ch[ai][al+k-1]=8;
ar=r;ai--;break;
}
for(;G[ai-1][al][ar]+ar==G[ai][al][ar];ai--)
for(int i=1;i<=ar;i++)
ch[ai][al+i-1]=8;
for(int r=ar+1;al+r-1<=m;r++)
if(F[ai-1][al][r]+ar==G[ai][al][ar])
{
for(int k=1;k<=ar;k++)
ch[ai][al+k-1]=8;
ar=r;ai--;break;
}
for(;F[ai][al][ar]>0;ai--)
for(int i=1;i<=ar;i++)
ch[ai][al+i-1]=8;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
printf("%d ",ch[i][j]);
puts("");
}
}
return 0;
}