我的dp真是菜的一笔
你 不 会 不 预 处 理 就 想 D P 吧 ? 你不会不预处理就想DP吧? 你不会不预处理就想DP吧?
首先不预处理根本无法判断子矩阵是否满足要求
而且设计状态的时候必须把子矩阵的大小设计进去,这样的话空间是 O ( 100 0 4 ) O(1000^4) O(10004)
…
考 虑 预 处 理 , 处 理 a [ i ] [ j ] 表 示 ( i , j ) 最 多 往 上 延 伸 几 个 点 是 同 色 的 考虑预处理,处理a[i][j]表示(i,j)最多往上延伸几个点是同色的 考虑预处理,处理a[i][j]表示(i,j)最多往上延伸几个点是同色的
那 么 以 ( i , j ) 为 右 下 角 矩 阵 的 合 法 方 案 那么以(i,j)为右下角矩阵的合法方案 那么以(i,j)为右下角矩阵的合法方案
先 考 虑 单 列 \color{Red}先考虑单列 先考虑单列
设 k = a [ i ] [ j ] , 那 么 a [ i − k ] [ j ] 也 要 等 于 k 设k=a[i][j],那么a[i-k][j]也要等于k 设k=a[i][j],那么a[i−k][j]也要等于k
而 且 a [ i − 2 ∗ k ] [ j ] 要 大 于 等 于 k ( 最 上 面 那 层 多 了 可 以 不 选 ) 而且a[i-2*k][j]要大于等于k(最上面那层多了可以不选) 而且a[i−2∗k][j]要大于等于k(最上面那层多了可以不选)
这 样 的 话 单 列 就 有 一 种 方 案 了 这样的话单列就有一种方案了 这样的话单列就有一种方案了
考 虑 多 列 \color{Red}考虑多列 考虑多列
多 列 就 从 j − 1 列 转 移 过 来 就 好 了 多列就从j-1列转移过来就好了 多列就从j−1列转移过来就好了
先 判 断 颜 色 是 否 相 同 , 在 判 断 长 度 , 具 体 看 代 码 先判断颜色是否相同,在判断长度,具体看代码 先判断颜色是否相同,在判断长度,具体看代码
#include <bits/stdc++.h>
using namespace std;
const int maxn=1009;
char mp[maxn][maxn];
int n,m,a[maxn][maxn],f[maxn][maxn],ans;
int main()
{
cin >> n >> m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin >> mp[i][j];
//数组a预处理每个格子往上最多几个格子和自己相同
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if( i==1 || mp[i][j]!=mp[i-1][j] ) a[i][j]=1;
else a[i][j]=a[i-1][j]+1;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
int k=a[i][j],mid=i-k,up=i-2*k;//以这个作为右下角,子矩阵必须高3k
if( a[mid][j]!=k || a[up][j]<k ) continue;
f[i][j]=1;//单列
if( mp[i][j-1]==mp[i][j]&&mp[mid][j-1]==mp[mid][j]&&mp[up][j-1]==mp[up][j] )
{
if( a[i][j-1]==k&&a[mid][j-1]==k&&a[up][j-1]>=k )
f[i][j]+=f[i][j-1];
}
ans+=f[i][j];
}
cout << ans;
}