Plug and contour line and Dynamic Planning Based on connectivity state Compression

Source: Internet
Author: User
What is plug DP?

On an N * m Board (N and m are small:

  • Number of different Loops
  • Number of solutions with one loop passing through all points
  • Number of solutions that pass through partial points with one loop
  • The weight and maximum value of one path

This type of problem can usually be solved using the plug DP.

This type of problem is usually very obvious, but the code is too large and prone to errors, sometimes TLE sometimes MLE.

 

What is dynamic planning based on state compression?

Status compression-based dynamic planning is a special kind of dynamic planning problem that takes the set information as the state and the total number of States as the index level.

On the basis of State compression, the connectivity of several elements must be recorded in the state of a type of problem. We call this problem a Dynamic Programming Problem Based on the State compression.

 

What is plug?

For a 4-connection problem, it usually has four plug s up and down. The plug in one direction indicates that the grid can be connected to the outside in this direction.

The grid on one road must go from one direction to another. There are 6 possibilities shown in the figure.

 

What is a contour line?

The blue line in the figure is called a contour line.

At any time, only the grids above the contour line have a direct impact on the grids below the contour line.

Obviously, for the lattice of the m column, there are m + 1 plug information on the contour line, including the plug information above the m grid and the plug information on the left side of the current grid.

 

General Solution

In the process of solving the problem, the contour line is transferred as the state of dynamic planning. Recurrence by grid. Each grid is considered in order from top to bottom and from left to right.

The grid d in the third column of the third row in the above edge contour diagram is used as an example. Suppose it has been pushed to it by grid:

Because there is a plug IV in the top grid, D must have an upward plug.

If there is a plug III in the left lattice, D must have a plug to the left. (D can only be the top left plug)

If there is a plug II in the grid on the left, D cannot have a plug to the left. (D can be the upper/lower or upper right plug)

When there is a right plug on the left and a down plug on the top (plug III and plug IV exist), D must have a top left plug.

In recursive mode, you need to calculate the right-side plug based on the plug on the left.

 

Recurrence by grid:

 

Connectivity

If the question requires a loop, what we get is possible.

How can we ensure that there is only one connected component in the graph.

We use the smallest notation to represent the connectivity of the lattice.

All obstacle grids are marked as 0, the first non-obstacle lattice, and all grids connected to it are marked as 1, then find the first unmarked non-obstacle grid and the grid connected to it marked as 2 ,......, Repeat this process until all the grids are marked.

When two grids belonging to different connected components are merged, we update the connectivity of all the grids belonging to the two connected components so that they have the same value.

 

Algorithm Description

Recurrence by grid. At the beginning of each row, an array is used to represent the contour line. m elements are stored in the array, that is, M columns. Is there a downward plug in each column in the previous row.

At the beginning of each grid, we need to know whether there is a plug on the left side of the grid and whether there is a plug on the top.

At the end of each grid, we need to set the plug of the grid in the same column in the next line and the plug information on the right of the current grid.

For ease of processing, we need to represent the contour line when it is recursive to each grid with an integer. This process is called encode.

For the lattice of M columns, a m + 1 array code is used to represent information (including connectivity) on the contour line ).

For the current lattice (I, j), the code [J-1] contains the plug information for its left lattice, the plug information for its top lattice in code [J.

We process all possible states of (I, j) based on these two values, and then set the Code [J-1] To the plug information of the lower lattice of (I, j, code [J] is set to the right plug information of (I, j.

Encode the code array as an integer and use it as the starting state of the (I, j + 1) lattice.

When J is the last column, all elements in the Code array are translated to the right, and the code [0] of the first element is set to 0.

In this way, for a new column, the Code array can represent the information of all the grids above it.

For connectivity problems, the Code array stores the connectivity of the plug.

For non-connectivity issues, whether the code Array Storage plug is available.

 

Code Implementation

[Example] Formula 1 [ural1519]

Here is an M * n chessboard. Some grids are obstacles. Ask how many circuits make it happen once every non-obstacle grid. M, N ≤ 12.

First, read the checkerboard. Set the barrier to 0 and the barrier to 1. Make sure that all the grids outside the checkerboard are barrier.

The question requires that all grids pass through. This means that when a grid forms a closed loop, there will be no other blank grids after it, therefore, the grid that forms the closed loop must be the rightmost lattice, expressed by (ex, ey.

memset(maze,0,sizeof(maze));  ex=ey=0;  for (int i=1;i<=n;i++){      scanf("%s",s+1);      for (int j=1;j<=m;j++){          if (s[j]==‘.‘){              maze[i][j]=1;              ex=i;              ey=j;          }      }  }  

 

 

We use two hash tables to store all possible states of the current grid contour line and all possible states of the next grid contour line.

This status may appear in F.

struct HASHMAP{      int head[seed],next[maxn],size;      LL state[maxn];      LL f[maxn];      void clear(){          size=0;          memset(head,-1,sizeof(head));      }      void insert(LL st,LL ans){          int h=st%seed;          for (int i=head[h];i!=-1;i=next[i]){              if (state[i]==st){                  f[i]+=ans;                  return;              }          }          state[size]=st;          f[size]=ans;          next[size]=head[h];          head[h]=size++;      }  }hm[2];  

The main processing process is as follows. Two hash tables are stored in turn. Recursive lattice. If it is not accessible, dpblank is called; otherwise, dpblock is called.

After recursion, the number of solutions in all possible states is added as the answer. In fact, for this question, there will only be one state, that is, all the elements in the Code array are 0, because there cannot be a downward plug on the last line.

int cur=0;  LL ans=0;  hm[cur].clear();  hm[cur].insert(0,1);  for (int i=1;i<=n;i++){      for (int j=1;j<=m;j++){          hm[cur^1].clear();          if (maze[i][j]) dpblank(i,j,cur);          else dpblock(i,j,cur);          cur^=1;      }  }  for (int i=0;i

The encoding process is not complex, as long as the status compression knowledge is used to store the values in the array in different bits of an integer according to certain rules.

Because m is <= 12 in the question, it is clear that there are at most six different connected components. Therefore, the value of the element in the Code array should not exceed 6, and three binary bits are used to represent 0 ~ An integer of 7.

Note that during the pressure bit process, a connected component will be removed when the plug with different connectivity is merged, so you need to re-process the connectivity number and re-press 1 ~ CNT encoding.

LL encode(int code[],int m){      LL st=0;      int cnt=0;      memset(ch,-1,sizeof(ch));      ch[0]=0;      for (int i=0;i<=m;i++){          if (ch[code[i]]==-1) ch[code[i]]=++cnt;          code[i]=ch[code[i]];          st<<=3;          st|=code[i];      }      return st;  }  

Decoding is simpler.

void decode(int code[],int m,LL st){      for (int i=m;i>=0;i--){          code[i]=st&7;          st>>=3;      }  

The shift function moves all elements in the code one to the right. This is required when J = m.

void shift(int code[],int m){      for (int i=m;i>0;i--) code[i]=code[i-1];      code[0]=0;  }  

When processing an empty position, enumerate all possible contour states.

For each status, decode the code array first.

Left = Code [J-1] on its left, and up = Code [J] on the top.

We will discuss the situation in the general solution.

When there is a plug on the top left, when the two plug belong to the same connected component, if this grid is exactly the last grid, the loop can be merged. When the two plugs do not belong to the same connected component, merge them.

If there is a plug on the left or a plug on the top, determine whether the right or the bottom is an obstacle. If not, connect a plug, this plug is the same connected component as the plug connected to this grid.

For a grid without a plug, it can only be a new connected component. Set the plug to the right. Set the new connected component to the maximum value that cannot be generated. When encoding is performed, the component is reset, so you don't have to worry about overflow.

For each State discussed, add it to the next hash table.

If J = m, shift is required before encoding, but in some cases J cannot be equal to M. Therefore, shift is not required.

void dpblank(int i,int j,int cur){      int left,up;      for (int k=0;k

A barrier cannot have a downward or right plug. Set it to 0.

void dpblock(int i,int j,int cur){      for (int k=0;k

This entire process is actually a plug-in DP template (from the kuangbin Daniel ).

 

Classic Problems

HDU 1693 eat the trees

Number of solutions with multiple loops passing through all grids.

You do not need to record connectivity. The simplest question is to consider proper plug for all spaces.

Ural 1519 Formula 1

Number of Solutions for a single loop passing through all grids.

Make sure that only the last grid is used to form a loop.

Fzu 1977 Pandora adventure

There are three types of single-loop grids: obstacle grids, required grids, and optional grids.

When encoding, add a flag to indicate whether a loop is formed. If a required grid is still encountered after the loop is formed, this state will be discarded.

HDU 1964 Pipes

Calculate the minimum cost for a single loop.

The question of cost calculation is changed to the current best value during hash. A loop can be formed only when the last grid is determined.

HDU 3377 plan

You can select a grid from the upper left corner to the lower right corner. Each grid has a score and the maximum score is obtained.

The upper-left and lower-right grids are processed separately. The upper-left grids can only have downward or right plugs, while the lower-right grids can only have upward and downward plugs, and cannot form a loop.

Poj 1739 Tony's tour

From the lower-left corner to the lower-right corner, each non-obstacle grid only takes the number of methods once.

Add the last two rows, and the middle part of the last two rows is set as an obstacle. Then, find the number of solutions for a loop.

Poj 3133 Manhattan Wiring

There are two 2 in the grid, two 3. connect two 2 and two 3. The two paths cannot be crossed.

For the points 2 and 3 separately, the grid cannot form a loop, and there are only two possibilities, and there are only four possible directions.

Connectivity only has two options: 2 or 3. If you are not sure about 2 or 3, try both of them.

Zoj 3466 the hive II

Multiple circuits go through the hexagonal lattice with obstacles and calculate the number of solutions.

Turn the grid row and column upside down, and find a grid with six direction plug, left and right, plus two lower two above.

Expanding the code array to double, a grid occupies three elements in the Code array, code [2 * J-2] is the left plug, code [2 * J-1] is the top left plug, code [2 * j] is the upper right plug.

After derivation according to different situations, code [2 * J-2] is the lower left plug, code [2 * J-1] is the lower right plug, code [2 * j] is the right plug. In this way, the next lattice can still obtain the appropriate information from the code.

The calculation method for the lower left and lower right coordinates of the odd and even rows is different. Pay attention to the processing. Due to the particularity of the hexagonal, only the even rows need shift operation.

Zoj 3213 beautiful meadow

Use a simple path to obtain the maximum score.

HDU 4285 Circuits

Calculate the number of solutions for K circuits. Cannot be nested.

Press the current number of closed loops into the status.

For ring rings, if there is an odd number of plug with different connectivity components on the left of the current grid, if a closed loop is formed on the top left of the current grid, the ring rings will appear, skip this step.

 

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.