首页 > 其他 > 详细

洛谷 P2051 [AHOI2009]中国象棋

时间:2018-09-05 20:42:19      阅读:151      评论:0      收藏:0      [点我收藏+]

题意简述

在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\n", ans);
}

洛谷 P2051 [AHOI2009]中国象棋

原文:https://www.cnblogs.com/xuyixuan/p/9594103.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!