JakeLin- [Blue Bridge Cup] Checkerboard Polynomial-Problem Solution

The problem of the eight queens is to put queens on the chessboard and not to attack each other and seek solutions. If you change the pieces, you can also have the problem of eight cars, eight horses, eight soldiers, and eight kings. In this problem, the chess pieces were replaced by cars, and the chess board had to be replaced. To be precise, some modifications were made. For example, there is now an n * n chess board. We pick a few holes in some grids. Naturally, these holes cannot be used for chess pieces, and they will be missed. In addition, a car could have attacked with its peers. Now, if you think about it, if you step on a hole during the attack, you will destroy yourself. Therefore, the attack range of the car ends at the hole. 
For this question, give you the scale n of the chessboard, and the digging situation. Find the number of plans for placing k cars (k from 0 to the maximum number of cars that can be placed). 

Data scale and convention 
n <= 8 

Input

An integer n in the first line indicates the size of the chessboard. 
Next n lines. Each line has n numbers 0 or 1 separated by spaces. The shape of 0 indicates holes, and 1 indicates no holes. 

Output

Several rows, the i-th row represents the number of plans to put i cars 

Sample input

3
1 0 1
1 1 1
1 0 1

Sample output

7
12
4

Title link (submittable)

As the title says, this question is based on the classic question of the retrospective method: "n Queen's Question"  . Before deeply understanding this question, it is strongly recommended to poke the previous article to enhance the understanding of " n Queen's Question"   "N Queen And 2N queen problem analysis "


I. Brief introduction to n Queen's problem

Did you see the step variable in the above article, it refers to the placement of the step queen, and it also refers to the placement of the queen in the step line, because:

The n queen problem can only be put into n queens, and there is only one in each row and only one in each column!

When we determine the step, iterate through each column of this row to find the position that meets the conditions.


Second, how is this question different from the n queen problem

In the question: Now, if you step on a hole during the attack, you will destroy yourself. Therefore, the attack range of the car ends at the hole.
Example: a line is 1 0 1

If the first column of this line drops a car, the third column will not be attacked, because the car's attack range ends at the hole in the second column.
and so:

Q: When we know that point (i, j) is visited, where do we need to go to find the next location ?
Answer: Yes, we need to traverse all the points after (i, j) to find the qualified position, and the same column can also be used .

Q: So what is a qualified position ?
Answer: We assume that the position is (x, y)
on the same line: if there is 1 in (x, 1 ~ y), and there is no 0 between them, then it will be attacked, not a legal position, otherwise Even if the safe position is
on the same column: if there is 1 in (1 ~ x, y), and there is no 0 blocking between them, then it will be attacked, not a legal position, otherwise even the safe position

Here we write a check () to determine whether a certain point (x, y) is safe:

bool check(int x,int y,int n) {
    for(int i=x-1; i>=1; i--) {
        if(map[i][y]==0) break; //如果在遇到1之前遇到0,那么它是安全的 
        if(vis[i][y]==1) return false; //如果还没遇到0就遇到了1,那就它是危险的 
    }
    for(int i=y-1; i>=1; i--) {
        if(map[x][i]==0) break;
        if(vis[x][i]==1) return false;
    }
    return true;
}

Three, how to achieve

As with the n queen problem, the process is implemented using the DFS algorithm, explaining the variables:

dfs(int x,int y,int t,int n) // 访问了(x,y);此时t个车;n为棋盘规模
int num[maxn] // num[i]表示i个车的方案数

DFS algorithm process, the specific analysis is written in the code:

void dfs(int x,int y,int t,int n) {
    if(t<=n*n) num[t]++;
    for(int i=x; i<=n; i++) {  //遍历 (x,y)及其之后的所有点,从(1,1)开始
        int j;  // 遍历:x行y列之后的+下面所有行
        if(i==x) j=y;
        else j=1;
        for(;j<=n; j++) {
            if(vis[i][j]==0 && map[i][j]==1 && check(i,j,n)) { //满足条件的访问:没访问过 && 是陆地 && 不被攻击
                vis[i][j]=1;
                dfs(i,j,t+1,n);
                vis[i][j]=0;  // 回溯到DFS前的状态
            }
        }
    }
}

The complete code is as follows: 

#include<cstdio>
#include<iostream>
using namespace std;
const int maxn = 10;
int map[maxn][maxn];
int vis[maxn][maxn];
int num[maxn];
bool check(int x,int y,int n) {
    for(int i=x-1; i>=1; i--) {
        if(map[i][y]==0) break; //如果在遇到1之前遇到0,那么它是安全的 
        if(vis[i][y]==1) return false; //如果还没遇到0就遇到了1,那就它是危险的 
    }
    for(int i=y-1; i>=1; i--) {
        if(map[x][i]==0) break;
        if(vis[x][i]==1) return false;
    }
    return true;
}
void dfs(int x,int y,int t,int n) {
    if(t<=n*n) num[t]++;
    for(int i=x; i<=n; i++) {
        int j;
        if(i==x) j=y;
        else j=1;
        for(;j<=n; j++) {
            if(vis[i][j]==0 && map[i][j]==1 && check(i,j,n)) {
                vis[i][j]=1;
                dfs(i,j,t+1,n);
                vis[i][j]=0;
            }
        }
    }
}
int main() {
    int n;
    cin>>n;
    for(int i=1; i<=n; i++) {
        for(int j=1; j<=n; j++) {
            cin>>map[i][j];
        }
    }
    dfs(1,1,0,n);
    for(int i=1; i<=n*n;i++) {
        if(num[i]!=0) cout<<num[i]<<endl;
    }
    return 0;
}

If it helps you, it is a great honor!

Published 20 original articles · won 15 · views 217

Guess you like

Origin blog.csdn.net/qq_37414463/article/details/105373646