Status compression dynamic planning POJ 2411 (beauty of programming-tile overlay floor)

Source: Internet
Author: User

After-school questions of the beauty of programming are also the same as the whole question. (P269)

Question

It is easy to understand the meaning of this question. In an N * M lattice, we now have two types of bricks: 1*2 and 2*1, how many solutions can be used to fill up the entire N * M space.

The simplest example is as follows:


Programming-US-China questions:

One summer, the Microsoft Asia Research Institute, located on the fourth floor of the magma building, made a large renovation of the office building patio. the original floor is paved with N × M square tiles, which are damaged and aged and need to be updated. when they went to the store to buy new ceramic tiles, they found that the store currently only supplies rectangular ceramic tiles. The current rectangular tile is equivalent to the original two square tiles, the workers may not decide how much they should buy. Readers may ask for help to analyze: Can I use 1 × 2 tiles to cover N × M floors?

Here we refer to the analysis of the first statement. In fact, the second statement is the same idea:


This topic category belongs to the state compression DP. The simplest understanding of the State compression DP is to express the State in the form of bits. We will use the example below to illustrate it.

Assume that we are in the brick position (I, j) and we have already laid the previous position. In this position, we choose:

1. No need to paving the bricks, may have been in the (I-1, j) moment has been vertically paved, and then consider (I, j + 1)
2. paving bricks horizontally and (I, j + 1). Then, consider (I, j + 2)

3. Build a vertical ro (I, j) AND (I + 1, j.


So we will translate our selection as follows. If we choose to stick bricks horizontally in the position (I, j), (I, j + 1) all are filled in as 1. If there is a vertical tile, we enter (I, j) as 0 and (I + 1, j) as 1.

Why do we need to count it like this? I think we should understand it as follows:

1. When the tiles are stacked horizontally, (I, j) AND (I, j + 1) are all 1. This value does not affect the selection of the next line.

2. We chose 1 when the second brick was erected. Because the brick was over, it still had no impact on how to choose the next line.

3. the first vertical brick has an impact on the following. If (I, j) is 0, then (I + 1, j) only when the value is 1 can the conditions be met.


(This involves the following status compatibility issues)


One advantage of choosing vertical tiles is that when processing the last row, we can ensure that the last row is 1, because the last row cannot start with vertical bricks, therefore, it is easy to obtain the final solution.


Okay, let's draw a picture of the solution we understand in this way:

 

If we understand each row as a binary number

Row1 = 51, Row2 = 15, Row3 = 48, Row4 = 63, Row5 = 51, Row6 = 63.

The last line must be 1.

We use DP (I, j) to indicate the number of solutions that can be used when row I reaches status j. So obviously our final goal is to calculate DP (N, 2 ^ (M-1)-1 );


Let's take a simple look at why the problem can meet the dynamic planning requirements. Now the analysis object is DP (I, j ), how many laying methods are related to the previous line,

If a State DP (I-1, k) on the previous line can reach DP (I, j) We think these two States are compatible if DP (I-1, k) it is compatible with DP (I, j) and DP (I-1, k) has S laying scheme, so DP (I, j) can be from DP (I-1, k)

This path is used to obtain S solutions. Of course, the value of k here can be 0 ~~~~ 2 ^ (M-1)-1 values.


Now let's understand what j is and k is compatible.

In fact, we have basically provided the analysis above. If we are laying (I, x) x here, it indicates row I, column x

1. If the value of row I and the value of j on the x bit is 0, then the value of j on the I-1 line is 1. Because it is impossible to place the first two vertical columns in the adjacent positions of the same column. If I, x + 1 is used for the next test, otherwise the system returns an incompatible result.


2. If the value is in line I, the value of j at the position x is 1.

{


There are two possible cases:

1. (I-1, x) is 0, this time must be laid vertically, the next detection is (I, x + 1)

2. (I-1, x) is 1, if so, then (I, x) must be chosen to lay horizontally, then (I, x + 1) it must also be 1, and (I-1, x + 1) must be 1 (if it is 0, is the vertical spread), if not satisfied, return incompatible, test if conditions are met (I, x + 2)

}


For the compatibility of the first line, let's make a special analysis. In the first line, either put 0 or 1.

Add the bit x of DP (0, j) to the test, that is, row 0th and column x.

1. If x is 1, then x + 1 must be 1, and then test x + 2.

2. If x is 0, directly test the next x + 1


Note that, in a test loop, we sometimes have to move one digit, sometimes two digits, and two digits and x = M-1 (M columns) it indicates that it is no longer compatible.


According to the above analysis, it is not difficult to write the code:

[Cpp]
# Include <stdio. h>
# Include <memory. h>
# Include <math. h>
# Include <algorithm>
Using namespace std;
 
 
# Define MAX_ROW 11
# Define MAX_STATUS 2048
Long DP [MAX_ROW] [MAX_STATUS];
Int g_Width, g_Height;
 
Bool TestFirstLine (int nStatus) // test the first line
{
Int I = 0;
While (I <g_Width)
{
If (nStatus & (0x1 <I ))
{
If (I = g_Width-1 | (nStatus & (0x1 <(I + 1) = 0)
{
Return false;
}
I + = 2;
}
Else
{
I ++;
}
}
Return true;
}
 
Bool CompatablityTest (int nStatusA, int nStatusB) // test if status (I, nStatusA) and (I-1, nStatusB) is compatable.
{
Int I = 0;
 
While (I <g_Width)
{
If (nStatusA & (0x1 <I) = 0)
{
If (nStatusB & (0x1 <I) = 0)
{
Return false;
}
I ++;
}
Else
{
If (nStatusB & (0x1 <I) = 0)
{
I ++;
}
Else if (I = g_Width-1) |! (NStatusA & (0x1 <(I + 1) & (nStatusB & (0x1 <(I + 1 )))))
{
Return false;
}
Else
{
I + = 2;
}
 
}
}
Return true;
}
Int main ()
{
Int I, j;
Int k;
While (scanf ("% d", & g_Height, & g_Width )! = EOF)
{
If (g_Width = 0 & g_Height = 0)
{
Break;
}
 
If (g_Width> g_Height)
{
Swap (g_Width, g_Height );
}
 
 
Int nAllStatus = 2 <(g_Width-1 );
Memset (DP, 0, sizeof (DP ));
For (j = 0; j <nAllStatus; j ++)
{
If (TestFirstLine (j ))
{
DP [0] [j] = 1;
}
}
 
For (I = 1; I <g_Height; I ++)
{
For (j = 0; j <nAllStatus; j ++) // iterate all status for line I
{
For (k = 0; k <nAllStatus; k ++) // iterate all status for line I-1
{
If (CompatablityTest (j, k ))
{
DP [I] [j] + = DP [I-1] [k];
}
}
}
}
Printf ("% lld \ n", DP [g_Height-1] [nAllStatus-1]);
}
Return 0;
}

Note: Because the algorithm complexity is H * (W ^ 4), when W> H, we exchange them to reduce the complexity.

In addition, the data is relatively large, so long (_ int64) is used)

Author: hopeztm

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.