Luogu P1896 [SCOI2005] mutual non aggression (shape pressure dp)

Posted by lilRachie on Fri, 18 Feb 2022 08:03:58 +0100

Title Description

Title address: P1896 [SCOI2005] mutual non aggression

In N × There are K kings in N's chessboard so that they don't attack each other. How many placement schemes are there. The king can attack one grid in its upper, lower, left, lower, left, lower, right, upper, right and lower eight directions, a total of 8 grids.
Input format
There is only one line containing two numbers N , K ( 1 < = N < = 9 , 0 < = K < = N ∗ N ) N,K ( 1 <=N <=9, 0 <= K <= N * N) N,K(1<=N<=9,0<=K<=N∗N)
Output format
Number of schemes obtained
Sample input and output
input

3 2

output

16

Depth first search 70 points:

In line with the principle of writing a violent search and cheating points if you can make a violent search, write a dfs when you come up. Violent search still needs to be skilled. Unexpectedly, the positive solution of optimization also has points!

1. Place the king line by line from left to right. There are two options for each new grid (x,y): place or not. If there is a conflict when placing here, you can only choose not to place, that is, only recursive search is used. If the king placed here will not conflict with the previous placement, you need to search for both placement and non placement.
2. Some details:
(1) Since it is placed from left to right line by line, just check whether the king has been placed in the four directions of top left, top right, top right and left.
(2) Set the starting point of dfs to (0,N), and judge whether the current position is at the end of a line at the entrance of recursion: if it is at the end of a line, you need to jump to the next line, otherwise continue to place it to the right. The advantage of this is that it can search the position (1,1) with or without. In addition, only when "k kings have been placed", "no more kings can be placed" and "k kings have not been placed at (N,N)", can the recursive return be made. If the position is not changed to "legal position" at the recursive entrance, but the position after crossing the boundary is regarded as a search state and returned, the whole search state will be destroyed. If you draw the search tree of dfs, you will find this problem. (it can be understood by analogy with the treatment of crossing the boundary in a simple maze problem. If you don't understand it, it won't affect the problem.).
3. Preliminary estimation of time complexity: regardless of the recursive return caused by "k kings have been placed" and "some positions can only be selected", there are two choices for each grid, that is, the time complexity is 2 N ∗ N 2^{N*N} 2N∗N. For the scale of N=9, it must timeout.

//C++For details of the search code, see the note:
#include<iostream>
  using namespace std;
  typedef long long LL;
  int grid[20][20];  //Store the status of the chessboard. A grid[x][y] of 1 means to place the king, and a grid of 0 means not to put it
  int N,K;
  LL res=0;     //Number of recording schemes
  
  //Judge whether the position (x,y) can be placed
  bool check(int x,int y){
  if(!grid[x-1][y]&&!grid[x][y-1]&&!grid[x-1][y-1]&&!grid[x-1][y+1]) return true;
  return false;
  }
  
  //dfs Parameter Description: the current position is (x,y), and the number of Kings placed is k
  void dfs(int x,int y,int k){  
  if(k==K){res++;return;} //Put enough K kings and increase the number of schemes
  if(y==N){x++;y=1;}  //When you reach the end of a row, you jump to the first column of the next row   
  else y++;     //Otherwise right    
  if(x>N) return;  //Search the whole chessboard and end the search
  dfs(x,y,k);     //Search for non placement
   
  if(check(x,y)){   //If there is no conflict, try placing
  grid[x][y]=1;   
  dfs(x,y,k+1);   //Search for next status  
  grid[x][y]=0;   //Undo placement on Backtracking
  }
  }
  
  int main(){
  cin>>N>>K;
  dfs(0,N,0);
  cout<<res<<endl;
  return 0;
  }

Full Score positive solution of pressure dp

1. Use a binary number to indicate the king placement of a line: if the i-th digit is 1, it means that the king is placed at position I, and 0 means that there is no king. For example, the number 10 corresponds to binary ( 1010 ) 2 (1010)_{2} (1010) 2, indicating that the king is placed at the second and fourth positions from right to left in the row; The number 15 corresponds to binary ( 1111 ) 2 (1111)_{2} (1111) 2 indicates that the king is placed in the first four positions from right to left; The number 42 corresponds to binary ( 101010 ) 2 (101010)_{2} (101010) 2 , indicates that the king is placed in the second, fourth and sixth positions of the line from right to left.
2. For a number, its placement status may be illegal. For example, the binary of 11 is ( 1011 ) 2 (1011)_{2} (1011) 2, there is a conflict between two kings in the placement state of the representative. How to check whether the placement status represented by a number is legal? If number x x If there are two adjacent 1s in the binary of x, it is illegal, so you can move it to the right by one bit and the original number, and then judge whether it is legal or not. Namely x & ( x < < 1 ) x\&(x<<1) X & (x < < 1) is 0 0 0 does not conflict, otherwise it conflicts.
3. For two numbers representing the relationship between upstream and downstream x x x and y y y. How to judge whether there is conflict: if x & y x\&y If X & Y is 0, the two rows will not conflict directly above and below, x & ( y < < 1 ) x\&(y<<1) X & (y < < 1) and ( x < < 1 ) & y (x<<1)\&y (x < < 1) &y are 0 0 0, there will be no conflict between upper left (right) and lower left (right).
3. Define dp[i][s][k] as the number of schemes that are "currently placed on line I, the placement status of the current line is s, and K kings have been placed". Next, determine the state transition equation: from the forward thinking, it can be seen that the state that dp[i][s][k] can recursively arrive is the state of "placed on line i+1, placed in ss, and kk kings have been placed", where ss is a state that is legal and has no conflict with s, and the relationship between kk and K is the number of 1 in the binary number corresponding to kk=k+ss. The definition function get(x) returns the number of 1 in the binary of X (get(x) represents the number of Kings placed in this line in the corresponding placement state of x), then the above forward recursive process can be expressed as dp[i+1][ss][k+get(ss)]+=dp[i][s][k]. Reverse thinking determines that the final state transition equation is dp[i][s][k]+=dp[i-1][ss][k-get(s)].

#include<iostream>
     using namespace std;
     const int n=12;
     typedef long long LL;
     LL dp[n][1<<n][n*n];
     
     int get(int x){
     int cnt=0;
     while(x){
     x-=x&(-x);
     cnt++;
     }
     return cnt;
     }
     
     int check1(int x){
     return (x&(x<<1))==0;
     }
     
     int check2(int x,int y){
     if(x&y) return 0;
     if((x<<1)&y) return 0;
     if(x&(y<<1)) return 0;
     return 1;
     }
     
     int main(){
     int N,K;
     cin>>N>>K;
     for(int i=1;i<=N;i++){
        for(int s=0;s<(1<<N);s++){
            if(check1(s)){
              if(i==1) {dp[i][s][get(s)]=1;}
                else{
                   for(int ss=0;ss<(1<<N);ss++){
                     if(check2(s,ss)&&check1(ss)){
                         for(int j=get(s);j<=K;j++){
                            dp[i][s][j]+=dp[i-1][ss][j-get(s)];
                        }
                    }
                }
              }
            }
        }
     }
     LL res=0;
     for(int s=0;s<(1<<N);s++) res+=dp[N][s][K];
     cout<<res<<endl;
     return 0;
     }


Topics: C++ Dynamic Programming