zoukankan      html  css  js  c++  java
  • Bzoj 4806 炮 (dp)

    题目描述

    众所周知,双炮叠叠将是中国象棋中很厉害的一招必杀技。炮吃子时必须隔一个棋子跳吃,即俗称"炮打隔子"。 
    炮跟炮显然不能在一起打起来,于是rly一天借来了许多许多的炮在棋盘上摆了起来……他想知道,在N×M的矩形
    方格中摆若干炮(可以不摆)使其互不吃到的情况下方案数有几种。
    棋子都是相同的。

    输入输出格式

    输入格式:
    一行,两个正整数N和M。
    N<=100,M<=100
    输出格式:

    一行,输出方案数mod 999983。

    输入输出样例

    输入样例#1: 
    1 3
    
    输出样例#1: 
    7

    分析 :

    显然一行一列只能放2个或以下棋子, 否则会相互攻击;
    明显的DP;
    定义f[i][j][k] , 表示前i行, 有j列是放了1个, k列放了两个;

    转移方程 :

    f[i][j][k] += f[i-1][j][k] 什么都没放;
    f[i][j][k] += f[i-1][j-1][k] * (m - (j - 1) - k) 在没放棋子的一列放了一个;
    f[i][j][k] += f[i-1][j+1][k-1] * (j + 1) 在有一个棋子的一列放了一个, 变成了两个;
    f[i][j][k] += f[i-1][j-2][k] * C(m - (j - 2) - k, 2) 在没放棋子的两列分别放两个棋子;
    f[i][j][k] += f[i-1][j][k-1] * j * (m - (j - 1) - k) 直接在没放棋子的一列放上两个棋子;
    f[i][j][k] += f[i-1][j+2][k-2] * C(j + 2, 2) 在放了一个棋子的两列风别放上一个;

    记得取模;

    代码奉上
    // By zZhBr
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    const int p = 999983;
    #define int long long
    
    int n, m;
    
    int f[105][105][105];
    
    int ans;
    
    signed main()
    {
        cin >> n >> m;
        
        f[0][0][0] = 1;
        
        for(register int i = 1 ; i <= n ; i ++)
        {
            for(register int j = 0 ; j <= m ; j ++)
            {
                for(register int k = 0 ; k <= m - j ; k ++)
                {
                    
                    f[i][j][k] = (f[i][j][k] + f[i-1][j][k]) % p;
                    
                    if(j - 1 >= 0)
                        f[i][j][k] = (f[i][j][k] + f[i-1][j-1][k] * (m - (j - 1) - k)) % p;
                    
                    if(k - 1 >= 0)
                        f[i][j][k] = (f[i][j][k] + f[i-1][j+1][k-1] * (j + 1))% p;
                    
                    if(j - 2 >= 0)    
                    {    
                        int t = m - (j - 2) - k;
                        f[i][j][k] = (f[i][j][k] + f[i-1][j-2][k] * (t * (t - 1)) / 2) % p;
                    }
                    
                    if(k - 2 >= 0)
                        f[i][j][k] = (f[i][j][k] + f[i-1][j+2][k-2] * (j + 1) * (j + 2) / 2) % p;
                    
                    if(k - 1 >= 0)
                        f[i][j][k] = (f[i][j][k] + f[i-1][j][k-1] * j * (m - (j - 1) - k)) % p;
                    
                    if(i == n) ans = (ans + f[i][j][k]) % p;
                    
                    //printf("n == %lld,  f[i][j][k] == %lld
    ", i, f[i][j][k]);
                }
            }
        }
        
        cout << ans << endl;
        
        return 0;
    }
    zZhBr



    提交地址 https://www.lydsy.com/JudgeOnline/problem.php?id=4806 ;





  • 相关阅读:
    centos5.8下用shell脚本监控服务器
    linux下IPTABLES配置详解
    centos设置计划任务(cron)
    32位CentOS系统安装kernel-PAE支持4g以上内存
    Excel同时打开多个独立的窗口
    yum安装LAMP
    多字段指定不同方向排序
    MySQL基础
    Python 网络编程
    Python 并发编程
  • 原文地址:https://www.cnblogs.com/BriMon/p/8949340.html
Copyright © 2011-2022 走看看