1. 程式人生 > 實用技巧 >[CF1393D] Rarity and New Dress - dp

[CF1393D] Rarity and New Dress - dp

Description

給定一個 \(n \times m\) 的網格,每個格子有一個顏色,問有多少個同色菱形。\(n,m \le 2000\)

Solution

類似“最大正方形”的套路,設 \(f[i][j]\) 表示以 \((i,j)\) 點為下頂點的菱形的最大邊長,轉移時考慮 \((i,j),(i-1,j),(i-2,j),(i-1,j-1),(i-1,j+1)\) 這五個點是否相等,如果相等則從 \(f[i-1][j],f[i-2][j],f[i-1][j-1],f[i-1][j+1]\) 中取最小值轉移過來即可。

#include <bits/stdc++.h>
using namespace std;

#define int long long 
const int N = 2005;

char a[N][N];
int f[N][N],n,m;

signed main()
{
    ios::sync_with_stdio(false);

    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>a[i]+1;
    
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) f[i][j]=1;

    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(i>1 && j>1)
    {
        if(a[i-1][j-1]==a[i-1][j] && a[i-1][j+1]==a[i-1][j] && a[i-2][j]==a[i-1][j] && a[i][j]==a[i-1][j])
        {
            f[i][j]=max(f[i][j],min(min(f[i-1][j-1],f[i-1][j+1]),min(f[i-1][j],f[i-2][j]))+1);
        }
    }

    int ans=0;
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) ans+=f[i][j];

    cout<<ans<<endl;
    return 0;
}