zoukankan      html  css  js  c++  java
  • 洛谷 P2051 [AHOI2009]中国象棋

    题意简述

    在N行M列的期盘中,放若干个炮,使它们两两不能打到,求总共的方案数

    题解思路

    DP,dp[i][j][k]表示前i行有j列放置1个炮,有k列放置2个炮
    分6种情况转移
    1.不放炮,直接到下一行
    2.在没放炮的那一列放1个炮,j+1
    3.在没放炮的两列分别放1个炮,j+2
    4.在放一个炮的那一列放1个炮,j-1,k+1
    5.在放一个炮的两列分别放1个炮,j-2,k+2
    6.同时在没放炮的一列和放一个炮的一列分别放一个炮,k+1

    代码

    #include <cstdio>
    using namespace std;
    typedef long long ll;
    const int mod = 9999973;
    int n, m, ans;
    int dp[200][200][200];
    void add(int &x, int y) {x = ((ll)x + y) % mod; }
    int C(int x) {return (ll)x * (x - 1) / 2 % mod; }
    int main()
    {
    	scanf("%d%d", &n, &m);
    	dp[0][0][0] = 1;
    	for (register int i = 0; i <= n; ++i)
    		for (register int j = 0; j <= m; ++j)
    			for (register int k = 0; k <= m - j; ++k)
    			{
    				add(dp[i + 1][j][k], dp[i][j][k]);
    				if (m - j - k) add(dp[i + 1][j + 1][k], (ll)dp[i][j][k] * (m - j - k) % mod);
    				if (m - j - k >= 2) add(dp[i + 1][j + 2][k], (ll)dp[i][j][k] * C(m - j - k) % mod);
    				if (j) add(dp[i + 1][j - 1][k + 1], (ll)dp[i][j][k] * j % mod);
    				if (j >= 2) add(dp[i + 1][j - 2][k + 2], (ll)dp[i][j][k] * C(j) % mod);
    				if (m - j - k && j) add(dp[i + 1][j][k + 1], (ll)dp[i][j][k] * (m - j - k) * j % mod);
    			}
    	for (register int i = 0; i <= m; ++i) 
    		for (register int j = 0; j <= m - i; ++j)
    			add(ans, dp[n][i][j]);
    	printf("%d
    ", ans);
    }
    
  • 相关阅读:
    Tomcat笔记
    HAProxy简介
    Ansible简介与实验
    DHCP&PXE&Cobbler简单实现
    Keepalived实现LVS-DR集群高可用
    Web of Science爬虫(WOS、SCI):风车WOS下载器
    梦境时分,记录梦境
    基层码农谈领导力
    企业部署 Kubernetes 的终极目标是什么
    Scrum 敏捷实践中的三大角色
  • 原文地址:https://www.cnblogs.com/xuyixuan/p/9594103.html
Copyright © 2011-2022 走看看