Domino covering state compression dynamic programming

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/weixin_45707147/article/details/102759018

Here Insert Picture Description
Here Insert Picture Description
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;			
	}
}

Guess you like

Origin blog.csdn.net/weixin_45707147/article/details/102759018