"Dynamic Programming-state compression" square tiling problem

Question 1

There is a square n rows and m columns, need 1 * 2 small brick blanket, can not overlap each other between the small brick, asked how many different shop law?

answer

Assume f [ i ] [ j ] f[i][j] denotes i i -line, status j j number of programs. In the state j j , the 1 1 represents the on end of the upper half of the rectangle. 0 0 represents the rest.

Obviously row of vacant part is certainly to be placed vertically.

Sideways to see the rest of the two can not be two consecutive placement.

Clearly state transition: f [ i ] [ j ] = f [ i 1 ] [ k ] f[i][j]=\sum f[i-1][k]

The key is how should we choose a legitimate state.

  • Condition 1 : j   a n d   k = 0 j\ and\ k=0
  • The reason : to ensure that the upper part of the 1 1 below certain vacancies.
  • Condition 2 : j   O r   k of two Enter system 0. j \ or \ k in binary consecutive odd not 0.
  • The reason : o r or result of the operation in either the current line and the previous line and the vertically composition, or is composed of the current and next line or vertical. Anyway, 0 0 form must be filled by the cross-lay, so there must be an even number of consecutive 0 0 .

code show as below:

#include <bits/stdc++.h> 

#define int long long

using namespace std;
const int N = 12;

int n, m;
int ok[1<<N], f[N][1<<N];

signed main(void)
{
	freopen("floor.in","r",stdin);
	freopen("floor.out","w",stdout);
	cin >> n >> m;
	for (int i=0;i<(1<<m);++i)
	{
		int j = i;
		bool flag = 0, cnt = 0;
		for (int j=m-1;j>=0;--j)
		    if (i >> j & 1) flag |= cnt, cnt = 0;
		    else cnt ^= 1;
		ok[i] = (flag|cnt)^1;
	}
	f[0][0] = 1;
	for (int i=1;i<=n;++i)
		for (int j=0;j<(1<<m);++j)
		    for (int k=0;k<(1<<m);++k)
		        if ((j & k) == 0 && ok[k|j] == 1)
				    f[i][j] += f[i-1][k];
	cout<< f[n][0] << endl;
	return 0; 
}

Question 2

Given n ×× m (1≤n, m≤9) of the checkerboard, as not to overlap with domino rectangular cover 12 and L-shaped (minus a 22 angle) dominoes, find the number of full coverage scheme.

answer

This relatively iffy question, we need to use dfs to resolve.

We consider the current line state s1, s2 and state relations on line to transfer. Obviously there f [ i ] [ s 1 ] = f [ i 1 ] [ s 2 ] f[i][s1]=\sum f[i-1][s2]

The problem is the legitimacy of the transfer.

When we transfer each line, each and every attempt to enumerate, if the right impact, that is, if you want to extend to the right, then tagged with a variable, the next shift when the special sentence can be.

b1 indicate whether the column currently being received influence, whether that is already occupied. Is 1, or that the front row for 0.b2.

Note that the previous line state flag state to be the opposite of, for example, to fill to the previous line, then transfer the state is empty.

Here Insert Picture Description

Distance is this.

code show as below:

#include <bits/stdc++.h>

#define int long long

using namespace std;
const int N = 12;

int n, m, i;
int f[N][1<<N];

void dfs(int k,int s1,int s2,int b1,int b2) 
{
	if (k > m && b1 == 0 && b2 == 0) f[i][s2]+=f[i-1][s1];
	if (k > m) return; 
	dfs(k+1,s1*2+1-b1,s2*2+b2,0,0);
	if (b2 == 0) dfs(k+1,s1*2+1-b1,s2*2+1,0,1);
	if (b2 == 0) dfs(k+1,s1*2+1-b1,s2*2+1,1,1);
	if (b1 == 0) dfs(k+1,s1*2,s2*2+b2,1,1);
	if (b1 == 0 && b2 == 0) dfs(k+1,s1*2,s2*2+1,0,0);
	if (b1 == 0 && b2 == 0) dfs(k+1,s1*2,s2*2+1,1,0);
	if (b1 == 0 && b2 == 0) dfs(k+1,s1*2,s2*2+1,0,1);
	return;
}

signed main(void)
{
	freopen("examsix.in","r",stdin);
	freopen("examsix.out","w",stdout);
	cin>>n>>m;
	f[0][(1<<m)-1] = 1;
	for (i=1;i<=n;++i) dfs(1,0,0,0,0);
	cout<<f[n][(1<<m)-1];
	return 0;
} 

Guess you like

Origin blog.csdn.net/Ronaldo7_ZYB/article/details/94429613