zoukankan      html  css  js  c++  java
  • BZOJ 1801 [AHOI 2009] 中国象棋(DP)

    题意

    在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮。 请问有多少种放置方法。
    N,M <= 100

    题解

    发现每行每列都最多放两个,直接按行DP。

    f[i][j][k]f[i][j][k]表示到第ii行,有jj列放了11个,kk列放了22个。

    那么这一行就有三种情况:

    • 不放
    • 11个,又有两种情况
      • 放在之前没有棋子的列上
      • 放在已经有11个棋子的列上
    • 22个,有三种情况
      • 两个都放在没有棋子的列上
      • 两个都放在已经有11个棋子的列上
      • 一个放在没有棋子的列上,一个放在已经有11个棋子的列上

    转移显然。

    CODE

    #pragma GCC optimize ("O2")
    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 105;
    const int mod = 9999973;
    int f[MAXN][MAXN][MAXN], n, m;
    inline int calc(int n) { return (1ll * n * (n-1) / 2) % mod; }
    int main () {
    	scanf("%d%d", &n, &m);
    	f[0][0][0] = 1;
    	for(int i = 1; i <= n; ++i)
    		for(int j = 0; j <= m; ++j)
    			for(int k = 0; k+j <= m; ++k) {
    				f[i][j][k] = f[i-1][j][k];
    				
    				if(j) f[i][j][k] = (f[i][j][k] + 1ll * f[i-1][j-1][k] * (m-(j-1)-k) % mod) % mod;
    				if(k) f[i][j][k] = (f[i][j][k] + 1ll * f[i-1][j+1][k-1] * (j+1) % mod) % mod;
    				
    				if(j>1) f[i][j][k] = (f[i][j][k] + 1ll * f[i-1][j-2][k] * calc(m-(j-2)-k) % mod) % mod;
    				if(k>1) f[i][j][k] = (f[i][j][k] + 1ll * f[i-1][j+2][k-2] * calc(j+2) % mod) % mod;
    				if(j) f[i][j][k] = (f[i][j][k] + 1ll * f[i-1][j][k-1] * (m-j-(k-1)) % mod * j % mod) % mod;
    			}
    	int ans = 0;
    	for(int j = 0; j <= m; ++j)
    		for(int k = 0; k+j <= m; ++k)
    			ans = (ans + f[n][j][k]) % mod;
    	printf("%d
    ", (ans + mod) % mod);
    }
    
  • 相关阅读:
    [rabbitmq] python版本(六)远程过程调用
    [rabbitmq] python版本(五) 主题交换机
    物体运动学习笔记(一)
    基于TimeLine编辑角色动画(二)
    基于TimeLine编辑角色动画(一)
    SQlite常用操作封装
    unity三种资源加载方式Resources,AssetBundle,WebRequset的同步异步加载
    场景同步异步加载
    XML保存账号密码
    unity EditorWindow 绘制时间刻度
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039224.html
Copyright © 2011-2022 走看看