SRM553 Div1 500

来源:互联网 发布:c语言的应用场景 编辑:程序博客网 时间:2024/06/05 03:13
/*    终态分析:对于一个情况(以某一个为标准)最后答案一定是 对于每一行来说的一个单调数列            如  000001       11100                000011   或  11100                000011       11000                011111       10000    我们用A[i][j]表示我们可以做到使第i行使(1,i)为黑(i+1,m)为白    if(A[i][j])dp[i][j]+=dp[i-1][j];从上一行转移下来 */#include<bits/stdc++.h>#define For(i,l,r)for(int i=(l);i<=(r);i++)using namespace std;const int M=55,P=1e9+7;int A[M][M],dp[M][M],n,m;char a[M][M];void Add(int &a,int b){a=(a+b)%P;}int ans;void F1(){    For(j,0,m)dp[0][j]=1;    For(i,1,n)For(j,0,m){        dp[i][j]=j?dp[i][j-1]:0;        if(A[i][j])Add(dp[i][j],dp[i-1][j]);    }Add(ans,dp[n][m]);}void F2(){    For(i,1,n/2)For(j,0,m)swap(A[n-i+1][j],A[i][j]);    F1();    For(i,1,n/2)For(j,0,m)swap(A[n-i+1][j],A[i][j]);}void S1(){    /*  形如下面的重复         000000        000000        111111        111111    */    For(i,0,n){        int f=1;        For(j,1,i)if(!A[j][m])f=0;        For(j,i+1,n)if(!A[j][0])f=0;        ans-=f;    }   }void S2(){    /*  形如下面的重复         11000        11000        11000        11000    */    For(j,0,m){        int f=1;        For(i,1,n)f&=A[i][j];        ans-=f;    }}void All(){    /*  形如下面的被减了两次要加回来         11111        11111        11111        11111    */    For(i,1,n)For(j,1,m)if(a[i][j]=='W')return;    ++ans;}void solve(){    For(i,1,n)For(j,0,m){        A[i][j]=1;        For(k,1,j)if(a[i][k]=='W')A[i][j]=0;        For(k,j+1,m)if(a[i][k]=='B')A[i][j]=0;    }    F1();F2();    S1();S2();All();}int main(){    scanf("%d %d",&n,&m);    For(i,1,n)scanf("%s",a[i]+1);       solve();    For(i,1,n)For(j,1,m){        if(a[i][j]=='W')a[i][j]='B';        else if(a[i][j]=='B')a[i][j]='W';    }    solve();    printf("%d\n",(ans+P)%P);}
1 0
原创粉丝点击