首页 技术 正文
技术 2022年11月18日
0 收藏 519 点赞 3,462 浏览 1736 个字

题意

给出一个\(n*m\)的\(0,1\)矩阵,若一个矩阵中的所有元素都相同,则这个矩阵的代价为\(0\),如果不是则选择一种将它分成两个子矩阵的方案,代价为所有方案中(两个子矩阵的代价的较大值+\(1\))的最小值。

\(n,m \leq 185\)

传送门

思路

\(dp[ i ][ j ][ k ][ l ]\) 表示左上角是 $( i , j ) $ 、右下角是 $ ( k , l ) $的矩阵的最小代价,四维扛不住。

因为如果每次从中间分,\(log(n)+log(m)\)次就变成\(1*1\)的格子,代价是 \(0\),所以答案最多是\(log(n)+log(m)\)。

因此可以将值放进状态中,$dp[ i ][ j1 ][ j2 ][ k ] $表示左上角是 \(( i , j1 )\)、右上角是 $ ( i , j2 ) $ 、用$ k $的代价,往下最长能延伸到哪行。

转移的时候考虑横着切与竖着切。令$ d = dp[ i ][ j1 ][ j2 ][ k ]$ :

  • 横着切:$ d = dp \space [ dp[ i ][ j1 ][ j2 ][ k-1 ] +1] \space [ j1 ][ j2 ][ k-1 ] $;

  • 竖着切:\([ j1 , j3 ] 和 [ j3+1 , j2 ]\) 就是分出的两部分;

    \(dp[ i ][ j1 ][ j3 ][ k-1 ]\) 和 \(dp[ i ][ j3+1 ][ j2 ][ k-1 ]\)的最小值是答案,\(d\)为最小值中的最大值。至此我们得出了\(O(m)\)的暴力转移。

    因为\(dp\)值明显随矩阵增大而减小,所以可二分\(j3\)。考虑二分找出最大的\(min( dp[ i ][ j1 ][ j3 ][ k-1 ] , dp[ i ][ j3+1 ][ j2 ][ k-1 ] )\)。(左比右大往左,反过来,总之越接近越好)

初始化出所有\(k=0\)的情况即可

#include <bits/stdc++.h>
const int N=190;
using std::max;
using std::min;
int n,m,a[N][N],sum[N][N],dp[N][N][N][15];
char c[N][N];
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%s",c[i]+1);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
if (c[i][j]=='.') a[i][j]=1;
else a[i][j]=0;
sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];
}
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
for (int k=j;k<=m;k++){
int l=i,r=n,ans=i-1;
while (l<=r){
int mid=(l+r)>>1;
int s=sum[mid][k]-sum[mid][j-1]-sum[i-1][k]+sum[i-1][j-1];
if (s==0 || s==(mid-i+1)*(k-j+1))
ans=mid,l=mid+1;
else r=mid-1;
}
dp[i][j][k][0]=ans;
}
int k=1;
for (k=1;dp[1][1][m][k-1]<n;k++)
for (int h=1;h<=m;h++)
for (int i=1;i<=n;i++)
for (int j1=1,j2=j1+h-1;j2<=m;j1++,j2++){
if (dp[i][j1][j2][k-1]==n){
dp[i][j1][j2][k]=n;
continue;
}
dp[i][j1][j2][k]=dp[dp[i][j1][j2][k-1]+1][j1][j2][k-1];//横
if(dp[i][j1][j2][k]==n) continue;
int l=j1,r=j2-1,ans=0;//竖
while (l<=r){
int mid=(l+r)>>1;
int x=dp[i][j1][mid][k-1],y=dp[i][mid+1][j2][k-1];
ans=max(ans,min(x,y));
if (x<y) r=mid-1;
else l=mid+1;
}dp[i][j1][j2][k]=max(dp[i][j1][j2][k],ans);
}
printf("%d\n",k-1);
}
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,999
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,511
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,357
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,140
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,770
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,848