[AHOI2009] Chinese chess

Keywords: Python

Description

Given a chessboard, put m guns on the chessboard, so that the two guns can not attack each other, and find out the number of schemes.

Solution

Consider the design of a dp, and define f[i][j][k] to represent the number of schemes with the first I row, one shot in column j and two shots in column K.

There is an obvious conclusion: if the scheme is legal, the maximum number of guns in any row (column) is 2.

Then we think about the transition, assuming the current state is (i, j, k), we have the following decisions:

At present, this line can not fire a single gun.

If there are more than 0 columns in a gun, then we can put a gun in this position.

If the number of columns to put a gun exceeds 0, then we can put a gun at this position.

If the number of columns that are not put in one gun is more than 1, then we can put two guns in this position. We need to find the combination number for the scheme number.

If the number of columns to fire a shot exceeds 0, and the number of columns not to fire exceeds 0, then we can fire a shot at each of these two positions.

If the number of columns to put a gun exceeds 1, then we can put two guns here. We need to find the combination number.

To sum up, we discuss the state transition with a time complexity of O(nm^2).

Code

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 int n, m;
 5 ll f[110][110][110];
 6 const int mod = 9999973;
 7 int calc(int x) {
 8     return x * (x - 1) / 2;
 9 }
10 int main() {
11     scanf("%d%d", &n, &m);
12     f[0][0][0] = 1;
13     for (register int i = 0; i < n; ++i) {
14         for (register int j = 0; j <= m; ++j) {
15             for (register int k = 0; k <= m; ++k) {
16                 f[i + 1][j][k] = (f[i + 1][j][k] + f[i][j][k]) % mod;
17                 if (m - j - k > 0) f[i + 1][j + 1][k] = (f[i + 1][j + 1][k] + f[i][j][k] * (m - j - k)) % mod;
18                 if (j > 0) f[i + 1][j - 1][k + 1] = (f[i + 1][j - 1][k + 1] + f[i][j][k] * j) % mod;
19                 if (j > 1) f[i + 1][j - 2][k + 2] = (f[i + 1][j - 2][k + 2] + f[i][j][k] * calc(j)) % mod;
20                 if (j > 0 && m - j - k > 0) f[i + 1][j][k + 1] = (f[i + 1][j][k + 1] + f[i][j][k] * j * (m - j - k)) % mod;
21                 if (m - j - k > 1) f[i + 1][j + 2][k] = (f[i + 2][j + 2][k] + f[i][j][k] * calc(m - j - k)) % mod;
22             }
23         }
24     }
25     ll ans = 0;
26     for (register int i = 0; i <= m; ++i)
27         for (register int j = 0; j + i <= m; ++j)
28             ans = (ans + f[n][i][j]) % mod;
29     printf("%lld\n", ans % mod);
30     return 0;
31 }
AC Code

Posted by acctman on Sat, 02 Nov 2019 11:04:45 -0700