题目
Description
Input
Output
一行一个整数,输出土地的不平整程度。
Sample Input
样例 1 输入:
3 3
…
.##
.##
样例 2输入:
6 7
.####.#
#…#.
#…#.
#…#.
.####.#
#…##
Sample Output
样例 1 输出:
2
样例 2输出:
4
Data Constraint
思路
反着做,变成每次把两个相邻的区间合并
枚举答案,维护f[i][j][k]表示当前第i行j~k列最多能向下到哪一行,g[i][j][k]表示列
每次先自己转移自己,然后考虑用另一个数组转移
比如对于当前的f[i][j][k],可以转到满足g[j][i][l]>=k的l(g已经转移过自己),画图理解
g同理
而当一个矩形包含另一个矩形时,被包含的矩形的操作次数必然不增,同理在某一条边界上缩一格时也不增
因此可以单调维护l
代码
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define Max(a,b) if (a<b)a=b
#define N 225
using namespace std;
int n,m,a[N][N],b[N][N],f[2][N][N][N];
char s[N];
int main()
{
freopen("land.in","r",stdin);
freopen("land.out","w",stdout);
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
scanf("%s",s+1);
for (int j=1;j<=m;j++)
b[i][j]=b[i-1][j]+(a[i][j]=(s[j]=='.'));
}
//init
for (int i=1;i<=n;i++)a[i][m+1]=a[i][m];
for (int j=1;j<=n;j++)
for (int k=j;k<=n;k++)
f[0][m+1][j][k]=f[1][m+1][j][k]=m+1;
for (int i=m;i;i--)
for (int j=1;j<=n;j++)
for (int k=j;k<=n;k++)
{
if (b[k][i]-b[j-1][i]&&b[k][i]-b[j-1][i]!=k-j+1)
f[0][i][j][k]=i;
else
if (a[k][i]!=a[k][i+1])f[0][i][j][k]=i+1;
else f[0][i][j][k]=f[0][i+1][j][k];
}
//init end(ok)
for (int yjy=0,o=0;;yjy++,o=!o)
{
if (f[o][1][1][n]>m)
{printf("%d\n",yjy);return 0;}
for (int i=1;i<=m;i++)
for (int j=1;j<=n;j++)
for (int k=j,g=j,G=0;k<=n;k++)
{
f[!o][i][j][k]=f[o][f[o][i][j][k]][j][k];
if (g>j)G=min(f[o][i][j][g-1],f[o][i][g][k]);
while (g<k&&G<=min(f[o][i][j][g],f[o][i][g+1][k]))
G=min(f[o][i][j][g],f[o][i][g+1][k]),g++;
Max(f[!o][i][j][k],G);
}
}
}