• 【BZOJ】1801 [Ahoi2009]chess 中国象棋(dp)


    题目

    传送门:QWQ

    分析

    发现我们关心的不是棋子的位置,我们只关心棋子数量就ok。

    首先每行每列最多两个棋子。这是显然的。

    然后我觉得本题最难的部分就是对行进行讨论,蒟蒻我一直被限制在了对格点讨论。。。。

    $dp[i][j][k] $放了前$i$行,有$j$列有1个棋子,有$k$列有2个棋子。转移就很显然了。

    代码

     1 #include <bits/stdc++.h>
     2 typedef long long ll;
     3 const int maxn=105;const ll MOD=9999973;
     4 
     5 ll dp[maxn][maxn][maxn];
     6 //dp[i][j][k] 放了前i行,有j列有1个棋子,有k列有2个棋子
     7 ll num(int x){return ll(x)*ll(x-1)/2;}
     8 using namespace std;
     9 int main(){
    10     int n,m;scanf("%d%d",&n,&m);
    11     dp[0][0][0]=1;
    12     for(int i=0;i<n;i++){ //放第i+1行
    13         for(int j=0;j<=m;j++){
    14             for(int k=0;k+j<=m;k++){
    15                 dp[i+1][j][k]=(dp[i+1][j][k]+dp[i][j][k])%MOD;
    16                 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; 
    17                 if(j>=1) dp[i+1][j-1][k+1]=(dp[i+1][j-1][k+1]+dp[i][j][k]*j)%MOD;
    18                 if(m-j-k>=2) dp[i+1][j+2][k]=(dp[i+1][j+2][k]+dp[i][j][k]*num(m-j-k))%MOD;
    19                 if(j>=2) dp[i+1][j-2][k+2]=(dp[i+1][j-2][k+2]+dp[i][j][k]*num(j))%MOD;
    20                 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;    
    21             }
    22         }
    23     }
    24     ll ans=0;
    25     for(int i=0;i<=m;i++)
    26         for(int j=0;j+i<=m;j++)
    27             ans=(ans+dp[n][i][j])%MOD;
    28     printf("%lld
    ",ans);
    29     return 0;
    30 }
  • 相关阅读:
    ES6学习之装饰器
    ES6学习之Class
    ES6学习之Async函数
    ES6学习之Generator函数
    for循环及break和continue的区别
    ES6学习之Iterator和For...of循环
    js检测对象属性
    ES6学习之Promise
    ES6学习之Reflect
    Visual Studio references中的package找不到
  • 原文地址:https://www.cnblogs.com/noblex/p/9420764.html
Copyright © 2020-2023  润新知