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!
  • 相关阅读:
    第十二周作业
    第十一周作业
    第十周作业
    第九周作业*
    #**第八周作业+预习作业**
    第七周作业
    Linux 日志查看常用命令
    Linux tar命令
    Java 数组
    设计模式 观察者模式(Observer)
  • 原文地址:https://www.cnblogs.com/LH2000/p/12507217.html
Copyright © 2011-2022 走看看