A bishop is a piece used in thegame of chess which is played on a board of square grids. A bishop can only movediagonally from its current position and two bishops attack each other if oneis on the path of the other. In the following figure, the dark squaresrepresent
the reachable locations for bishop B1 formits current position. The figure also shows that the bishops
B1and B2 are in attacking positions whereas
B1and B3 are not.
B2 and B3are also in non-attacking positions.
Now, given two numbers nand k, your job is to determine the number of ways one can put
kbishops on an n × nchessboard so that no two of them are in attacking positions.
Input
The input file maycontain multiple test cases. Each test case occupies a single line in the inputfile and contains two integers
n (1 ≤ n ≤ 30) and k (0 ≤ k ≤ n2).
A test case containing two zerosfor n and k terminates the input and youwon’t need to process this particular input.
Output
For each test case in the inputprint a line containing the total number of ways one can put the given numberof bishops on a chessboard of the given size so that no two of them are inattacking positions. You may safely assume that this number will be less
than 1015.
Sample Input
8 6
4 4
20 40
30 5
0 0
Sample Output
5599888
260
0
3127859642656
题意:两个象互不攻击,当且仅当它们不出于同一斜线,一个n*n的棋盘上放k个互不攻击的象有多少种方法。
思路:把棋盘染色成国际象棋的棋盘,那么只有同一颜色上的才会互相攻击,而且不同颜色的互不影响,那么我们分别算不同颜色的
方法。首先将黑白颜色的格子都取出来,那么我们可以考虑第i行放或者不放,如果不放的话结果不变,如果放的话,只有
(len[i]-j+1)的位置可以选,因为前面有(j-1)个会攻击到,那么状态转移是:
dp[i][j] = dp[i-1][j]+(dp[i-1][j-1]*(len[i]-j+1)){len[i]代表第i行的格子个数}因为len[i]不是递增的,其实我们将一半行后面的也拿到前面,结果是不影响的
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> typedef long long ll; using namespace std; const int maxn = 35; ll dp1[maxn][1005], dp2[maxn][1005]; ll len1[maxn], len2[maxn]; int n, k; void init() { len1[1] = len1[2] = 1; len2[1] = len2[2] = 2; for (int i = 3; i < maxn-2; i += 2) { len1[i+1] = len1[i] = len1[i-1] + 2; len2[i+1] = len2[i] = len2[i-1] + 2; } } int main() { init(); while (scanf("%d%d", &n, &k) != EOF && n+k) { memset(dp1, 0, sizeof(dp1)); memset(dp2, 0, sizeof(dp2)); for (int i = 0; i <= n; i++) dp1[i][0] = dp2[i][0] = 1; for (int i = 1; i <= n; i++) for (int j = 1; j <= k; j++) { dp1[i][j] = (len1[i] - j + 1) * dp1[i-1][j-1] + dp1[i-1][j]; if (i != n) dp2[i][j] = (len2[i] - j + 1) * dp2[i-1][j-1] + dp2[i-1][j]; } ll ans = 0; for (int i = 0; i <= k; i++) ans += dp1[n][i] * dp2[n-1][k-i]; printf("%lld\n", ans); } return 0; }