参考来源
https://blog.csdn.net/qq_37129433/article/details/81841855
具体思路看这篇博文我觉得就可以了。
图片
这个图片是其中一个样例
0 1组成的矩阵是数组a[i][j],用来状态转移。
下面的矩阵是数组dp[i][j],dp[ i ][ j ]表示从前面涂到这个点,有多少种方案
这个数组a的作用(转态转移),非常巧妙。
它将右上角的矩阵的值(126)通过中间传递到了左下角的矩阵。
这里对于每个B,都只把它和它的左边标记为0,右边标记为1。
所以数值能够从上面传递下来,而标记为0的部分刚好能阻隔。
代码
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
char mp[50][50];
ll dp[50][50];//dp[i][j]表示:第i行第j个左边全部填蓝的,右边全部填红色的个数。
int a[50][50];
ll n,m;
int check(int x,int y)//检测该行左、右
{
for(int i=1;i<=y;i++)
{
if(mp[x][i]=='R')
return 0;
}
for(int i=y+1;i<=n;i++)
{
if(mp[x][i]=='B')
return 0;
}
return 1;
}
int main()
{
scanf("%lld %lld",&m,&n);
for(ll i=1;i<=m;i++)
scanf("%s",mp[i]+1);
for(int i=1;i<=m;i++)
{
for(int j=0;j<=n;j++)
{
a[i][j]=check(i,j);//标记
}
}
for(int i=0;i<=n;i++)//对第一行
{
dp[1][i]=a[1][i];// 边界值,初始化
}
for(int i=1;i<=m;i++)
{
for(int j=0;j<=n;j++)
{
for(int k=0;k<=j;k++)//k<=j
{
dp[i][k]+=dp[i-1][j]*a[i][k];
}
}
}
ll ans=0;
for(int i=0;i<=n;i++)
{
ans+=dp[m][i];
}
printf("%lld\n",ans);
return 0;
}