Loading

AcWing3494. 国际象棋(状压DP)

众所周知,“八皇后” 问题是求解在国际象棋棋盘上摆放 8 个皇后,使得两两之间互不攻击的方案数。

已经学习了很多算法的小蓝觉得 “八皇后” 问题太简单了,意犹未尽。作为一个国际象棋迷,他想研究在 N×M 的棋盘上,摆放 K 个马,使得两两之间互不攻击有多少种摆放方案。

由于方案数可能很大,只需计算答案除以 1000000007 (即 109+7) 的余数。

如下图所示,国际象棋中的马摆放在棋盘的方格内,走 “日” 字,位于 (x,y) 格的马(第 x 行第 y 列)可以攻击 (x+1,y+2)、(x+1,y−2)、(x−1,y+2)、(x−1,y−2)、(x+2,y+1)、(x+2,y−1)、(x−2,y+1) 和 (x−2,y−1) 共 8 个格子。

QQ截图20210512104039.png

输入格式

输入一行包含三个正整数 N,M,K,分别表示棋盘的行数、列数和马的个数。

输出格式

输出一个整数,表示摆放的方案数除以 1000000007 (即 109+7) 的余数。

数据范围

对于 5% 的评测用例,K=1;
对于另外 10% 的评测用例,K=2;
对于另外 10% 的评测用例,N=1;
对于另外 20% 的评测用例,N,M≤6,K≤5;
对于另外 25% 的评测用例,N≤3,M≤20,K≤12;
对于所有评测用例,1≤N≤6,1≤M≤100,1≤K≤20。

输入样例1:

1 2 1

输出样例1:

2

输入样例2:

4 4 3

输出样例2:

276

输入样例3:

3 20 12

输出样例3:

914051446

暴搜会T。看到范围很小故考虑状压。因为m最大会到100,而n最大才为6,因此不能对行状压只能对列状压。注意到一个马可能发生冲突的位置是与其距离不超过2的位置,因此设\(dp[i][j][k][w]\)代表前i行且第i - 1行状态为j,第i行状态为k,用了w个马的方案数。转移方程见代码。注意转移时以及枚举j, k的时候要判断是否冲突,以及注意初始化和遍历的顺序(i为阶段要放在最外面)。

#include <bits/stdc++.h>
#define MOD 1000000007
using namespace std;
int n, m, K;
long long dp[120][1 << 6][1 << 6][25];//dp[i][j][k][w]表示前i列且当前列的前列状态为j,当前列状态为k,用掉w个马的方案数
int get(int x) {
	int xx = x, ans = 0;
	while(xx > 0) {
		if(xx & 1) {
			ans++;
		}
		xx /= 2;
	}
	return ans;
}
int main() {
	cin >> n >> m >> K;
	dp[0][0][0][0] = 1;//注意初始化
	for(int i = 1; i <= m; i++) {
		for(int p1 = 0; p1 < (1 << n); p1++) {
			for(int p2 = 0; p2 < (1 << n); p2++) {
				if(((p1 >> 2) & p2) || (p1 & (p2 >> 2))) {//转移之前的
					continue;
				} else {
					for(int p3 = 0; p3 < (1 << n); p3++) {
						if(((p3 >> 2) & p2) || (p3 & (p2 >> 2))) {//当前列这么放会和之前的发生冲突
							continue;
						}
						if(((p3 >> 1) & p1) || (p3 & (p1 >> 1))) {
							continue;
						}
						int num = get(p3);//当前第i行的马的个数
						for(int k = num; k <= K; k++) {
							dp[i][p2][p3][k] = (dp[i][p2][p3][k] + dp[i - 1][p1][p2][k - num]) % MOD;
						}
					}
				}
			}
		}
	}
	long long ans = 0;
	for(int i = 0; i < (1 << n); i++) {
		for(int j = 0; j < (1 << n); j++) {
			ans = (ans + dp[m][i][j][K]) % MOD;
		}
	}
	cout << ans;
	return 0;
}
posted @ 2021-06-02 18:00  脂环  阅读(126)  评论(0编辑  收藏  举报