Description
给出七张牌的水平竖直状态如下图:
两张水平牌可以组成一个
1×2
1
×
2
块,两张竖直牌可以组成一个
2×1
2
×
1
块,给出由这些牌组成的
n×m
n
×
m
矩阵,要求把该矩阵划分成若干
1×2
1
×
2
块和
2×1
2
×
1
块的不交并,且需满足所有
1×2
1
×
2
块的左边块所处列不相邻,问划分方案数
Input
第一行两个整数 n,m(1≤n,m≤250) n , m ( 1 ≤ n , m ≤ 250 ) 表示矩阵行列数,之后输入该 n×m n × m 矩阵
Output
输出方案数,结果模 109+7 10 9 + 7
Sample Input
Sample Output
3
Solution
所有 1×2 1 × 2 块的左边块所处列不相邻的限制使得有 1×2 1 × 2 的两列与其他列完全分离,以 dp[j] d p [ j ] 表示前 j j 列划分的方案数,那么若第列可以由若干 2×1 2 × 1 块组成则有转移 dp[j]+=dp[j−1] d p [ j ] + = d p [ j − 1 ] ,然后考虑第 j j 列和第列这两列出现 1×2 1 × 2 块的方案数,以 f[i][0/1] f [ i ] [ 0 / 1 ] 分别表示这两列前 i i 行完全划分且不出现/出现块的方案数,则有以下转移
f[0][0]=1,f[0][1]=0 f [ 0 ] [ 0 ] = 1 , f [ 0 ] [ 1 ] = 0
若第 i i 行的两个块可以组成块则 f[i][1]=f[i−1][0]+f[i−1][1] f [ i ] [ 1 ] = f [ i − 1 ] [ 0 ] + f [ i − 1 ] [ 1 ]
若第 i−1 i − 1 行和第 i i 行这四个块可以组成两个块则 f[i][0]=f[i−2][0],f[i][1]+=f[i−2][1] f [ i ] [ 0 ] = f [ i − 2 ] [ 0 ] , f [ i ] [ 1 ] + = f [ i − 2 ] [ 1 ]
最后 f[n][1] f [ n ] [ 1 ] 即为这两列出现 1×2 1 × 2 块的方案数,继而有转移 dp[j]+=dp[j−2]⋅f[n][1] d p [ j ] + = d p [ j − 2 ] ⋅ f [ n ] [ 1 ] , dp[m] d p [ m ] 即为答案
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=255;
#define mod 1000000007
int n,m,type[maxn][maxn],dp[maxn],f[maxn][2];
char s[3][maxn*5];
//0 hor
//1 ver
//2 both
int Solve(int L,int R)
{
int num=0;
for(int i=0;i<3;i++)
for(int j=L;j<=R;j++)
if(s[i][j]=='O')num++;
if(num==2||num==3)
{
if(s[0][R]=='O')return 1;
return 0;
}
if(num==6)
{
if(s[1][L]=='O')return 1;
return 0;
}
return 2;
}
int main()
{
scanf("%d%d",&n,&m);
scanf("%s",s[0]);
for(int i=1;i<=n;i++)
{
for(int j=0;j<3;j++)scanf("%s",s[j]);
int L=1,R=3;
for(int j=1;j<=m;j++)
{
type[i][j]=Solve(L,R);
L+=4,R+=4;
}
scanf("%s",s[0]);
}
//for(int i=1;i<=n;i++)
// for(int j=1;j<=m;j++)
// printf("%d%c",type[i][j],j==m?'\n':' ');
dp[0]=1;
for(int j=1;j<=m;j++)
{
if(n%2==0)
{
int flag=1;
for(int i=1;i<=n;i++)
if(type[i][j]==0)
{
flag=0;
break;
}
if(flag)dp[j]=(dp[j]+dp[j-1])%mod;
}
if(j>1)
{
f[0][0]=1,f[0][1]=0;
for(int i=1;i<=n;i++)
{
f[i][0]=f[i][1]=0;
if(type[i][j-1]!=1&&type[i][j]!=1)f[i][1]=(f[i-1][0]+f[i-1][1])%mod;
if(i==1)continue;
if(type[i-1][j-1]&&type[i-1][j]&&type[i][j-1]&&type[i][j])
{
f[i][1]=(f[i][1]+f[i-2][1])%mod;
f[i][0]=(f[i][0]+f[i-2][0])%mod;
}
}
dp[j]=(dp[j]+(ll)dp[j-2]*f[n][1]%mod)%mod;
}
}
printf("%d\n",dp[m]);
return 0;
}