Thought from: http://blog.pureisle.net/archives/475.html
The main idea is to indicate whether it is filled with 1 and%, and then construct the DP equation based on the state relationship between the two lines.
1. First initialize the first line to calculate the number of scenarios that the first row can be filled horizontally. This time CNT is 1 so in fact the legal dp[1][j] are 1
2. Then start building the second line to the last row
When constructing each row, enumerates the possible states of the previous row, and CNT + = achieves the number of methods in that state, thus calculating the DP value.
The last line of the state to take the reverse operation, to get the last line is 0 position, turn them into 1, simulate vertical fill.
Then the complete set is bitwise AND manipulated, and then the line is built.
3. Be careful to keep the number of columns as small as possible because the h*2^w in the number of loops makes the W small better.
Look at many because the comments are more, in fact, the code of this method is very small.
#include <iostream>#include<cstring>using namespacestd;intw,h;unsignedLong LongCnt=1;//for each overlayUnsignedLong Longdp[ -][1<< A];//Dp[i][j] Indicates how many ways to reach the J state of line I//The final answer is the way to fill the last line, so it's dp[h][(1<<W)-1]voidBuild_line (intLineint from,intcur) { //line is the row number of the currently constructed row//From is processing state//Cur is the location of the current processing if(cur = = W) {//one line of processing is over. Note: Cur is from 0 onwards to W-1dp[line][ from] +=CNT; return; } //keep the state unchanged and try to fill in the back buildBuild_line (Line, from, cur+1); //On the basis of the from State, continue to attempt to fill two consecutive horizontal empty//determine if the from can be filled horizontally two if(Cur <= w2 //Make sure you can fill in the two empty W-2 and W-1and! ( from& (1<<cur))//ensure that the location being processed and its next position is not filledand! ( from& (1<< (cur+1)) )// ){ //fill two blanks in a row horizontally intNext = from| (1<<cur) | (1<< (cur+1)); Build_line (Line,next,cur+2);//Continue building } return;}intMainintargcChar Const*argv[]) { while(1) {cin>>W>>i; if(w==0and h==0) Break; if(W > H) {//make the number of columns as small as possible to optimize efficiency because W is going to be exponential intT t = W; W = H; H =T; } //if it is an odd number of direct output 0 then determine the next state if(W*h%2==1) {cout<<0<<Endl; Continue; } //Empty ArrayMemset (DP,0,sizeof(DP)); CNT=1;//Reset to 1Build_line (1,0,0);//build the first row//enumerates all the states of the previous row from the second line to construct the bank for(inti =2; I <= H; ++i)//I is the line { for(intj =0; J < (1<<W); ++J)//J is the number of States that are enumerated i-1 rows { if(dp[i-1][J] >0){//If you can reach the J state of the previous lineCNT = dp[i-1][j]; }Else//invalid state returned directly Continue; //take the counter J and then perform the bitwise AND operation to obtain the condition that can be filled vertically.Build_line (i, (~j) & ((1<<W)-1) ,0); } } //Output ResultsCout<<dp[h][((1<<W)-1)]<<Endl; } return 0;}
"Algorithmic Learning Notes" 67. State compression DP SJTU OJ 1383 Smooth toothpick bag