P8675 [藍橋杯 2018 國 B] 搭積木

纯粹的發表於2024-05-22

原題連結

題解

1.請務必讀清題幹意思
2.如果以最頂端積木的位置為狀態,是可以窮盡所有情況的,則狀態為 \(dp[i][l][r]\) ,最頂端第 \(i\) 層只在區間 \([l,r]\) 內連續放置積木有幾種方法
3.狀態轉移方程 $dp[i][l][r]=\sum_1^l \sum_r^m dp[i+1][x][y] $
\(x,y\) 看成二維座標上的點,則上圖的sum可以用二維差分的方式求出

code

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll pre[105][105]={0};
int suf[105][105]={0};
ll dp[105][105][105]={0};
const ll mod=1e9+7;
int main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    ll n,m;
    cin>>n>>m;
    for(ll i=1;i<=n;i++)
    {
        string s;
        cin>>s;
        for(ll j=1;j<=m;j++)
        {
            pre[i][j]=pre[i][j-1]+(s[j-1]=='X');
        }
    }

    for(ll i=n;i>=1;i--)
    {
        for(ll l=1;l<=m;l++)
        {
            for(ll r=m;r>=l;r--)
            {
                if(pre[i][r]-pre[i][l-1]!=0) continue;
                if(i==n) dp[i][l][r]=1;
                else dp[i][l][r]=suf[l][r];
                dp[i][l][r]%=mod;
            }
        }

        for(int l=1;l<=m;l++)
        {
            for(int r=m;r>=1;r--)
            {
                suf[l][r]=((suf[l-1][r]+suf[l][r+1])%mod-suf[l-1][r+1])%mod+dp[i][l][r];
                suf[l][r]%=mod;
            }
        }
    }

    ll ans=1;
    for(ll i=1;i<=n;i++)
    {
        for(ll l=1;l<=m;l++)
        {
            for(ll r=l;r<=m;r++)
            {
                ans+=dp[i][l][r];
                //printf("(%d,%d,%d)  %d\n",i,l,r,dp[i][l][r]);
                ans%=mod;
            }
        }
    }
    cout<<ans;
    return 0;
}

相關文章