题意:
解法:
显然令d(i,j)表示走到(i,j)的方案数。
因为题目说每一步可以向右、向下、向右下走任意格,
因此d(i,j)可以由左边、上面、左上方转移而来,
可以看作是左边的dp(,)的和,上面的dp(,)和,左上的dp(,)的和,
那么用三个前缀和sum(,)维护一下前缀和,之后就可以O(1)转移了。
code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxm=2e3+5;
const int mod=1e9+7;
int a[maxm][maxm];
int d[maxm][maxm];
int sum1[maxm][maxm];//上
int sum2[maxm][maxm];//左
int sum3[maxm][maxm];//左上
int n,m;
signed main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
char c;cin>>c;
if(c=='.')a[i][j]=1;
}
}
d[1][1]=sum1[1][1]=sum2[1][1]=sum3[1][1]=a[1][1];
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(i==1&&j==1)continue;
if(!a[i][j]){
d[i][j]=sum1[i][j]=sum2[i][j]=sum3[i][j]=0;
continue;
}
d[i][j]=(sum1[i-1][j]+sum2[i][j-1]+sum3[i-1][j-1])%mod;
sum1[i][j]=(sum1[i-1][j]+d[i][j])%mod;
sum2[i][j]=(sum2[i][j-1]+d[i][j])%mod;
sum3[i][j]=(sum3[i-1][j-1]+d[i][j])%mod;
}
}
cout<<d[n][m]<<endl;
return 0;
}