zoukankan      html  css  js  c++  java
  • [AHOI2009]中国象棋

    链接

    https://www.luogu.com.cn/problem/P2051

    记录下第一次过省选难度的题。

    题目分析

    由题意可知每一列和每一行能同时存在的炮都不能超过2个,否则就会互殴。那么只需要记录每一行有1个炮的列数和有2个炮的列数递推即可。

    具体做法

    设状态dp[i][j][k]其中i代表行数,j代表该行有j列已经放置了一个棋子,k代表有k列已经放了2个棋子。

    之后只需要对当前行放置0,1,2棵炮的情况进行递推即可

    递推公式

    dp[i][j][k]=dp[i-1][j][k];
    if(j>=1)dp[i][j][k]+=dp[i-1][j-1][k]*(m-j-k+1);
    if(k>=1)dp[i][j][k]+=dp[i-1][j+1][k-1]*(j+1);
    if(j>=2)dp[i][j][k]+=dp[i-1][j-2][k]*(((m-j-k+2)*(m-j-k+1))/2);
    if(k>=1)dp[i][j][k]+=dp[i-1][j][k-1]*j*(m-j-k+1);
    if(k>=2)dp[i][j][k]+=dp[i-1][j+2][k-2]*(j+2)*(j+1)/2;

    上代码

    #include<bits/stdc++.h>
    #define mod 9999973
    using namespace std;
    long long dp[105][105][105];
    int main(){
        int n,m;
        cin>>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<=m-j;k++){
                    dp[i][j][k]=dp[i-1][j][k];
                    if(j>=1)dp[i][j][k]+=dp[i-1][j-1][k]*(m-j-k+1);
                    if(k>=1)dp[i][j][k]+=dp[i-1][j+1][k-1]*(j+1);
                    if(j>=2)dp[i][j][k]+=dp[i-1][j-2][k]*(((m-j-k+2)*(m-j-k+1))/2);
                    if(k>=1)dp[i][j][k]+=dp[i-1][j][k-1]*j*(m-j-k+1);
                    if(k>=2)dp[i][j][k]+=dp[i-1][j+2][k-2]*(j+2)*(j+1)/2;
                    dp[i][j][k]%=mod;
                }
            }
        }
        long long ans=0;
        for(int j=0;j<=m;j++){
            for(int k=0;k<=m;k++){
                ans+=dp[n][j][k];
            //    cout<<ans<<endl;
                ans%=mod;
            }
        }
        cout<<ans;
    } 
    rush!
  • 相关阅读:
    MySQL学习笔记(六):索引
    正则表达式基础知识,持续更新…
    js改变盒子大小(上下左右)分析
    表单自定义样式
    js拖拽分析
    javascript右键菜单分析
    简要分析javascript的选项卡和轮播图
    表单联动的总结
    浅显总结ASCII Unicode UTF-8的区别
    瀑布流知识的延伸
  • 原文地址:https://www.cnblogs.com/LH2000/p/12507217.html
Copyright © 2011-2022 走看看