[AC Wing] 1064. Small King

Subject address:

https://www.acwing.com/problem/content/1066/

At n × nn×nn×Putkkon the board of nk kings, the king can attack the neighboring8 88 grids, find the total number of solutions that make them unable to attack each other.

Input format:
one line, containing two integers nnn andkkk

Output format:
a total of one line, indicating the total number of solutions, if it cannot be placed, it will output 0 00

Data range:
1 ≤ n ≤ 10 1≤n≤101n10
0 ≤ k ≤ n 2 0≤k≤n^2 0kn2

The idea is dynamic programming. State compression can be used to store the king placement of each row, that is, an integer binary bit is used to express whether a king is placed in a certain position. Next, let f [i] [j] [s] f[i][j][s]f [ i ] [ j ] [ s ] means that it is currently on theiii row, a total ofjj areplacedj kings (including theiithe king of line i itself), and put it askkThe binary of k represents the number of solutions like this. Then the final requirement is ∑ s = 0 2 n − 1 f [n] [k] [s] \sum_{s=0}^{2^n-1} f[n][k][s]s=02n1f [ n ] [ k ] [ s ] Initial conditionsf [0] [0] [0] = 1 f[0][0][0]=1f[0][0][0]=1 , which means nothing is shown. For other situations, we can according to thei − 1 i-1iAccording to the arrangement of 1 row, there are: f [i] [j] [s] = ∑ p → sf [i − 1] [j − c (s)] [p] f[i][j] [s]=\sum_{p\to s} f[i-1][jc(s)][p]f[i][j][s]=psf[i1][jc ( s ) ] [ p ] wherec (s) c(s)c ( s ) meanssss in the11The number of 1 ,p → sp\to sps means that if thei − 1 i-1iWhen placed in one row, it isppp , then theiii row can be placed assss , that is, these two lines are not contradictory. Next, consider how the two states are not contradictory. Ifp & s = 1 p\& s=1p&s=1 orp ∣ sp|sp s has two consecutive1 11 , then there is a contradiction. The former means that there are two kings in two adjacent rows in the same column, and the latter means that there is a king on the upper left or upper right of a certain king in the next row. Everything else is possible. To speed up, we can preprocess all states1 1The number of 1 , and a certain statesss corresponding toppp . code show as below:

#include <iostream>
#include <vector>
using namespace std;

const int N = 11, M = 1 << 10, K = 110;
int n, k;
// 存某行可以放的国王合法状态(即没有两个连续的1)
vector<int> state;
// 存每个数的二进制表示里1的个数
int cnt[M];
// head[i]存哪些状态与i这个状态不矛盾
vector<int> head[M];
// 答案比较大,要用long来存
long f[N][K][M];

// 判断st是否不含两个连续的1,如果不含,就返回true,否则返回false
bool check(int st) {
    
    
    for (int i = 0; i < n; i++)
        if ((st >> i & 1) && (st >> i + 1 & 1))
            return false;
    return true;
}

// 返回st二进制里1的个数
int count(int st) {
    
    
    int cnt = 0;
    while (st) {
    
    
        st -= st & -st;
        cnt++;
    }
    return cnt;
}

int main() {
    
    
    cin >> n >> k;
    // 求一下合法状态,并且将它们的1的个数存下来
    for (int i = 0; i < 1 << n; i++)
        if (check(i)) {
    
    
            state.push_back(i);
            cnt[i] = count(i);
        }
	
	// 求一下对每个状态i,哪些状态j与之不矛盾
    for (int i = 0; i < state.size(); i++)
        for (int j = 0; j < state.size(); j++) {
    
    
            int a = state[i], b = state[j];
            if ((a & b) == 0 && check(a | b))
                head[i].push_back(j);
        }
	
    f[0][0][0] = 1;
    // 枚举摆放到第几行
    for (int i = 1; i <= n; i++)
    	// 枚举一共摆多少个国王
        for (int j = 0; j <= k; j++)
        	// 枚举当前行可以摆放的状态
            for (int cu = 0; cu < state.size(); cu++)
            	// 枚举第i - 1行可以摆放的状态
                for (int pr : head[cu]) {
    
    
                    int c = cnt[state[cu]];
                    if (c <= j) f[i][j][cu] += f[i - 1][j - c][pr];
                }

    long res = 0;
    for (int i = 0; i < state.size(); i++) res += f[n][k][i];

    cout << res << endl;

    return 0;
}

Time complexity O (nk 2 2 n) O(nk2^{2n})O ( n k 22 n ), but the actual complexity is not that high, because the number of legal states is much less than2 n 2^n2n , spaceO (nk 2 n) O(nk2^n)O ( n k 2n)

Guess you like

Origin blog.csdn.net/qq_46105170/article/details/114469893
ac