UVA - 10237 Bishops

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;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值