• BZOJ 4806 : 炮


    题目链接

    题意:炮在同一行或是同一列超过三个就可以出现一个吃掉另一个的情况,求在n*m的棋盘上放置炮且两两不可吃的情况总数。

    用dp的方法来完成计数,可以考虑这样一个状态,枚举到第x行,共有 a个“含2个炮的列”, b个“含1个炮的列”, c个“含0个炮的列”,注意到a+b+c等于定值,显然这是可以优化的。基本思路大概这样。

    dp[i][j][k]表示前i行里,具有{有j个“含1个炮的列”, k个“含2个炮的列”}性质的情况总数

    最后求ans时,要对dp[n][][]求总和

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    
    const int mod=999983;
    const int N=105;
    
    int n,m;
    LL dp[N][N][N];
    
    int cal(int x)
    {
        return x*(x-1)/2%mod;
    }
    
    int main()
    {
        while(~scanf("%d%d",&n,&m))
        {
            dp[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++)
                    {
                        dp[i][j][k]=dp[i-1][j][k];
                        if(j>=1) dp[i][j][k]=(dp[i][j][k]+dp[i-1][j-1][k]*(m-k-j+1))%mod;
                        if(j>=2) dp[i][j][k]=(dp[i][j][k]+dp[i-1][j-2][k]*cal(m-k-j+2))%mod;
                        if(k>=1) dp[i][j][k]=(dp[i][j][k]+dp[i-1][j+1][k-1]*(j+1))%mod;
                        if(k>=1) dp[i][j][k]=(dp[i][j][k]+dp[i-1][j][k-1]*(m-k-j+1)%mod*j)%mod;
                        if(k>=2) dp[i][j][k]=(dp[i][j][k]+dp[i-1][j+2][k-2]*cal(j+2))%mod;
                    }
            int ans=0;
            for(int i=0;i<=m;i++)
                for(int j=0;i+j<=m;j++)
                    ans=(ans+dp[n][i][j])%mod;
            printf("%d
    ",ans);
        }
    }
  • 相关阅读:
    设计模式-可复用面向对象软件基础笔记
    C#--笔记
    win系统下nodejs安装及环境配置
    三步将Node应用部署到Heroku上 --转载
    Ubuntu 重启命令
    Ubuntu ssh免密登录
    Ubuntu Hadoop环境搭建(Hadoop2.6.5+jdk1.8.0_121)
    Ubuntu vim使用
    Scala学习——array与arraybuffer的区别(初)
    Scala学习——可变参数(初)
  • 原文地址:https://www.cnblogs.com/Just--Do--It/p/7308141.html
Copyright © 2020-2023  润新知