It simply says this problem is to use dominoes to cover the 1x2 checkerboard NxM, how many kinds of programs. N, M <= 11.
Preliminary understanding
of our preliminary classification discussion of N:
when N = 1, M is odd, no solution, M is even, there is a unique solution
for N = 2, Fibonacci series
(they can find an example of a push)
in-depth analysis of
available N > how do 2:00?
Since N <= 11, is easy to think of the state of compression can be expressed by bit operation.
Difficulties: Status indicates: DP [i] [S] denotes the i-th row reaching, covering the current state S of the program number.
Domino to put sideways, two positions are set to 1
for the domino on end, above the set, the bottom is set to 0
then in the case, we set the behavior of a s1, a next behavior s2, may metastasis:
Case 1: s1 by 0, S2 corresponding bit must be 1
Case 2: S1 by 1, S2 corresponding bit may be 0, may be 1, but must satisfy s1 & s2 may be 1x2 covered
satisfy s1 & s2 may be 1x2 cover which is one difficulty understanding
For the main course of dynamic programming, there are
LL solve(int k, int S) { // 到达第k行,状态为S方案数
if (dp[k][S] != -1) return dp[k][S];
if (k == 1) {
if (S == two(m)-1) return dp[k][S] = 1;
else return dp[k][S] = 0;
}
dp[k][S] = 0;
for (int i = 0; i < two(m); ++i)
if ((i|S) == two(m)-1 && Cover(i&S)) //若可以转移
dp[k][S] += solve(k-1, i);
return dp[k][S];
}
Put the code
#include<iostream>
#include<cstring>
#define LL long long
using namespace std;
int h,w;
long long dp[15][(1<<11)+5];
bool check(int S)
{
for (int i=0;i<w;++i)
if(S&(1<<i))
{
if (i==w-1||!(S&(1<<(i+1))))return false;
++i;
}
return true;
}
LL solve(int k,int s)
{
if(dp[k][s]!=-1) return dp[k][s];
if(k==1)
{
if(s==(1<<w)-1) return dp[k][s]=1;
return dp[k][s]=0;
}
dp[k][s]=0;
for(int i=0;i<(1<<w);i++)
if((i|s)==((1<<w)-1) && check(i&s))
dp[k][s]+=solve(k-1,i);
return dp[k][s];
}
int main()
{
while(cin>>h>>w)
{
if(!h && !w) return 0;
memset(dp,-1,sizeof(dp));
cout<<solve(h+1,(1<<w)-1)<<endl;
}
return 0;
}
The above wording is recursive, recursive Let me now look to all the pre-first transfer.
The question is, how pre-treatment?
Represents the same meaning of 0 and 1,
for the i-th row and the i + 1 th row, which follows a certain lattice status:
transition a
i: i + 1 0: 1 // If a grid i-th row is 0, then the first row i + 1 corresponding to the job must be 1.
Transfer two
i: the i-th row lattice @ 1 is 1, there are two possibilities: that domino placed longitudinally below; or laterally disposed second domino
i + 1: 0 // above that regardless of how the grid placing the first row i + 1 may be 0, i.e., a first vertical grid placed domino.
Transfer three
i: 1 1 i + 1: 1 1 // i-th row and the i + 1 row are laterally aligned
dfs (i, j, k) denotes the i-th row, j is the state of the line, the next line is k state.
dfs (col + 1, (s1 << 1) | 1, s2 << 1); 1 above, the following is 0, heel dominoes.
dfs (col + 1, s1 << 1, (s2 << 1) | 1); above is 0, the following is 1, belong to two dominoes.
dfs (col + 2, (s1 << 2) | 3, (s2 << 2) | 3); above 11, below 11, is placed horizontally above the dominoes.
Core code
void dfs(int col, int s1, int s2)
{
if (col >= m) {
if (col == m) g[s2].push_back(s1);
return;
}
dfs(col+1, (s1<<1)|1, s2<<1);
dfs(col+1, s1<<1, (s2<<1)|1);
dfs(col+2, (s1<<2)|3, (s2<<2)|3);
}
Put the code
#include<vector>
#include<iostream>
#include<cstring>
using namespace std;
int h,w;
vector<long long> v[(1<<11)+5];
long long f[11+5][(1<<11)+5];
void dfs(int step,int up,int down)
{
if(step>=w)
{
if(step==w) v[down].push_back(up);
return ;
}
dfs(step+1,(up<<1)|1,down<<1);
dfs(step+1,up<<1,(down<<1)|1);
dfs(step+2,(up<<2)|3,(down<<2)|3);
}
int main()
{
while(cin>>h>>w)
{
if(!h&&!w) return 0;
memset(f,0,sizeof(f));
memset(v,0,sizeof(v));
if(h<w) swap(h,w);
dfs(0,0,0);
f[0][0]=1;
for(int i=0;i<=h;i++)
for(int j=0;j<(1<<w);j++)
for(int k=0;k<v[j].size();k++)
f[i+1][j]+=f[i][v[j][k]];
cout<<f[h+1][(1<<w)-1]<<endl;
}
}