其他分享
首页 > 其他分享> > P2051中国象棋(dp)

P2051中国象棋(dp)

作者:互联网

inline int c(int num) {//计算 C(num,2)
	return num * (num - 1) / 2 % mod;
}

ll dp[110][110][110];//dp[row][column_1][column_2],有1个棋子的列和有两个棋子的列
int n, m;

int main() {
	scanf("%d %d", &n, &m);
	dp[0][0][0] = 1;

	for (register int i = 0; i < n; ++i) {//放第i+1行
		for (register int j = 0; j <= m; ++j) {//有1个棋子的列
			for (register int k = 0; k + j <= m; ++k) {// 有2个棋子的列
				if (dp[i][j][k]) {
					dp[i + 1][j][k] = (dp[i][j][k] + dp[i + 1][j][k]) % mod; //不放棋子
					if (m - j - k >= 1)	dp[i + 1][j + 1][k] = (dp[i + 1][j + 1][k] + dp[i][j][k] * (m - j - k)) % mod;//在没有棋子的列放一个棋子
					if (j >= 1)	dp[i + 1][j - 1][k + 1] = (dp[i + 1][j - 1][k + 1] + dp[i][j][k] * j) % mod; //在有1个棋子的列放1个棋子
					if (m - j - k >= 2)	dp[i + 1][j + 2][k] = (dp[i + 1][j + 2][k] + dp[i][j][k] * c(m - j - k)) % mod; // 在没有棋子的列放两个棋子
					if (j >= 1 && m - j - k >= 1)	dp[i + 1][j][k + 1] = (dp[i + 1][j][k + 1] + dp[i][j][k] * j * (m - j - k)) % mod; // 在没棋子的列和有1个棋子的列各放一个棋子
					if (j >= 2)	dp[i + 1][j - 2][k + 2] = (dp[i + 1][j - 2][k + 2] + dp[i][j][k] * c(j)) % mod; //在有1个棋子的列放两个棋子
				}
			}
		}
	}

	ll ans = 0;
	for (register int i = 0; i <= m; ++i) {
		for (register int j = 0; i + j <= m; ++j) {
			ans = (ans + dp[n][i][j]) % mod;
		}
	}
	printf("%lld\n", ans);
	return 0;
}

标签:中国象棋,num,int,P2051,棋子,列放,dp,mod
来源: https://www.cnblogs.com/wanshe-li/p/13757309.html