codeforces 1247 E

我们发现,如果倒着考虑的话,每个点向下和向右能到达的范围是确定的。
所以我们倒着dp维护后缀和。
然后分上面还是左边进来的就行。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N = 2e3+5;
const ll mod = 1e9+7;
int n,m;
char a[N][N];
ll f[N][N],g[N][N],b[N][N],c[N][N];
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>m;
    if(n==1&&m==1){
        cout<<1<<' ';
        return 0;
    }
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)cin >> a[i][j];
    //倒着转移即可根据石头个数求前缀和
    f[n][m]=g[n][m]=1;
    for(int i=n;i>=1;i--){
        for(int j=m;j>=1;j--){
            if(i==n&&j==m)continue;
            if(j!=m)b[i][j]=b[i][j+1]+(a[i][j+1]=='R');
            if(i!=n)c[i][j]=c[i+1][j]+(a[i+1][j]=='R');
            f[i][j]=g[i][j+1]-g[i][m-b[i][j]+1];
            g[i][j]=f[i+1][j]-f[n-c[i][j]+1][j];
            (((f[i][j]+=f[i+1][j])%=mod)+=mod)%=mod;
            (((g[i][j]+=g[i][j+1])%=mod)+=mod)%=mod;
        }
    }
    ll ans = (f[1][1]-f[2][1]+g[1][1]-g[1][2])%mod;
    ans+=mod;ans%=mod;
    cout<<ans<<endl;
}

原文地址:https://www.cnblogs.com/MXang/p/11770453.html