BZOJ 1087 does not infringe on king, and bzoj1087 infringes on king.
Description
Put K kings in the N × N board so that they do not attack each other. The king was able to attack it, from top to bottom, and from top to left, from top to bottom, right to bottom, and from top to bottom, a grid near each other. There were 8 grids in total.
Input
Only one row contains N, K (1 <= N <= 9, 0 <= K <= N * N)
Output
Number of solutions.
Sample Input
3 2
Sample Output
16
First, this question uses the algorithm named squashed dp.
First, I declare that this blog does not apply to great gods !!!!!
King, the question of mutual non-infringement, first comes to mind the eight queens problem, but it is found that it is very different from the eight queens, because the eight queens are using the deep search method, however, according to the rules of the National elephant, the number of Queens that can be placed on a board is much less than that of the King, so DFS is enough.
So we should consider other methods, because the king's attack range is very small, only one circle around. However, we still cannot roll out all States (even if n <= 9 ). But we can find that as long as the first line is determined, we can introduce the following dynamic rules. In this way, we can use enumeration. During enumeration, we can use a binary representation of the State. This is a good comparison and can also compress the state. This is the idea of squashing the state. Here we can simulate it.
For example, n = 5. 1 indicates that the grid has a king, and 0 indicates that the grid has a king.
1 1 1 1 1 this situation obviously does not exist, so I have to exclude it. So how can we eliminate it? We consider the concept of bitwise operations. Move it to the right (>) (because the king's attack range is only 1 ). That is, 1 1 1 1 1 and then perform the (&) operation. If the returned value is 1, a conflict occurs. For example, in this case, 1 0 1 0 1 1 1 1 1 1 1 1 1. 1 0 1 0 1 The returned value is 0, so this situation exists. The binary value can be expressed in decimal number. If 1 1 1 1 1 1 decimal is 31, you can try to calculate 31 & (31> 1) = 1. While 1 0 1 0 1 decimal is 21,
21 & (21> 1) = 0. During comparison, both the left and right shifts are performed. In addition, we can perform preprocessing. The total number of States is 2 ^ n-1, and only loops are allowed. The Code is as follows:
Int check2 (int a) // a row's self-ratio {if (a & (a <1) return 0; if (a & (a> 1) return 0; return 1;} int get (int x) // The calculation state is x, where 1 is the number. {Int tot = 0; while (x) {if (x & 1) tot ++; x = x> 1 ;}return tot ;} int tot = (1 <n)-1; for (int I = 0; I <= tot; I ++) if (check2 (I )) {zt [++ num] = I; // status gs [num] = get (I); // Number of kings in this status}
Next we will talk about the dp process --
Int f [10] (I) [600] (j) [82] (k) {0}; // I indicates the number of rows, and j indicates the status j, k indicates the current total number of kings. f [I] [j] [k] indicates the number of schemes where k kings are stored in the j-th row.
Another preprocessing method is as follows. Comparing the statuses of the two rows can accelerate the comparison during the dp process.
Int check1 (int a, int B) // compare the two rows {if (a & (B <1) return 0; if (a & (B> 1 )) return 0; if (a & B) return 0; // compare the status when the two rows are not moved. As for why, manually add return 1 ;} for (int I = 1; I <= num; I ++) // pd [I] [j] = 1 indicates that I is in the next row of j in the previous row, and does not conflict with for (int j = 1; j <= num; j ++) if (check1 (zt [I], zt [j]) pd [I] [j] = pd [j] [I] = 1;
The main dp process is as follows:
For (int I = 0; I <n; I ++) // Number of cyclic rows, corresponding to the number of rows in the f array (I) for (int j = 1; j <= num; j ++) // cyclic state, corresponding to (j) for (int k = 0; k <= m; k ++) in the f array // Number of cyclic kings, corresponds to (k) if (f [I] [j] [k]) for (int q = 1; q <= num; q ++) in the array) // loop I the status of the next row if (pd [j] [q] & (k + gs [q] <= m )) // if conditions are met, continue f [I + 1] [q] [k + gs [q] + = f [I] [j] [k]; long int ans = 0; for (int I = 1; I <= num; I ++) // Add the f value of all States in row n to the answer ans + = f [n] [I] [m].
This is the main function. If you add other functions on your own, it makes no sense to reproduce the standard process !!
Note: f [0] [1] [0] = 1 indicates the initial state.