• 炮(棋盘DP)


    一行or一列上最多能放两个炮,因为炮会隔棋打,所以一列或者一行最多存在两个炮棋

    盘的状态压为三维

    dp[i][k][j]

    i:棋盘的第几行  k:前i行有几列放了一个炮棋  j:前i行有几列放了两个炮棋

    所以

    dp方程有6个元素:

    1:不放炮棋,所以方程为 dp[i][k][j]+=dp[i-1][k][j];

    2:往一个没有炮棋的列放一个炮棋,方程为dp[i][j][k]+=dp[i-1][k-1][j]*(m-k-j+1);

    3:往一个有一个炮棋的列放一个炮棋,方程为dp[i][j][k]+=dp[i-1][k+1][j-1]*(k+1);

    4:往一个有一个炮棋的列放一个炮棋同时往一个没有炮棋的列放一个炮棋,方程为dp[i][j][k]+=dp[i-1][k][j-1]*(k)*(m-j-k+1)/2;

    5:往一个有一个炮棋的列放一个炮棋同时往一个有一个炮棋的列放一个炮棋,方程为dp[i][k][j]+=(k+2)*(k+1)/2*dp[i-1][k+2][j-2];

    6:往一个没有炮棋的列放一个炮棋同时往一个没有炮棋的列放一个炮棋,方程为dp[i][k][j]+=(m-j-k+2)*(m-j-k+1)/2*dp[i-1][k-2][j];

     code:

    kailvxiugai 

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<algorithm>
    using namespace std;
    #define LL long long
    const int MAXN=201;
    const int mod=9999973;
    LL dp[MAXN][MAXN][MAXN];
    inline int calc( int num ) {
        return num*(num-1)/2;
    }
    int n,m;
    int main() {
    
        cin>>n>>m;
        dp[0][0][0]=1;
        for(int i=0; i<n;++i)
            for(int j=0;j<=m;++j)
                for(int k=0;k+j<=m;++k)
                    if(dp[i][j][k])
                    {
                        dp[i+1][j][k]=(dp[i+1][j][k]+dp[i][j][k])%mod;
                        if(m-j-k>=1) 
                            dp[i+1][j+1][k]=(dp[i+1][j+1][k]+dp[i][j][k]*(m-j-k))%mod;
                        if(j>=1) 
                            dp[i+1][j-1][k+1]=(dp[i+1][j-1][k+1]+dp[i][j][k]*j)%mod;
                        if(m-j-k>=2) 
                            dp[i+1][j+2][k]=(dp[i+1][j+2][k]+dp[i][j][k]*calc(m-j-k))%mod;
                        if(m-j-k>=1&&j>=1) 
                            dp[i+1][j][k+1]=(dp[i+1][j][k+1]+dp[i][j][k]*(m-j-k)*j)%mod;
                        if(j>=2) 
                            dp[i+1][j-2][k+2]=(dp[i+1][j-2][k+2]+dp[i][j][k]*calc(j))%mod;
                    }
        LL ans=0;
        for(int i=0;i<=m;++i)
            for(int j=0;j<=m-i;++j)
                ans=(ans+dp[n][i][j])%mod;
        printf("%lld",ans);
        return 0;
    }
  • 相关阅读:
    遍历及线索化二叉树
    二叉树
    程序的内存布局
    C语言一些易混淆的概念
    C语言标准库函数memcpy和memmove的区别以及内存重叠问题处理
    柔性数组
    一个基于QT简单登录对话框(带验证码功能)
    Qt中的布局管理器
    Qt中的标准对话框
    一个基于QT简单登录对话框
  • 原文地址:https://www.cnblogs.com/sssy/p/7205728.html
Copyright © 2020-2023  润新知