• 状压DP之中国象棋


    题目

    传送们
    这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法。大家肯定很清楚,在中国象棋中炮的行走方式是:一个炮攻击到另一个炮,当且仅当它们在同一行或同一列中,且它们之间恰好 有一个棋子。你也来和小可可一起锻炼一下思维吧!

    输入格式

    一行包含两个整数N,M,之间由一个空格隔开。

    输出格式

    总共的方案数,由于该值可能很大,只需给出方案数模9999973的结果。

    输入输出样例

    样例输入

    1 3 
    

    样例输出

    7
    

    思路

    定义dp[i][j][k]数组代表第i行中,有j列有一个棋子,有k列有两个棋子,我们从当前状态递推下一状态,有6种情况

    1. 不放棋子,(dp[i+1][j][k]=(dp[i+1][j][k]+dp[i][j][k])%mod);
    2. 在没有棋子的一列中放一个棋子,(dp[i+1][j+1][k]=(dp[i+1][j+1][k]+dp[i][j][k]*(m-j-k))%mod);
    3. 在没有棋子的两列中放棋子,(dp[i+1][j+2][k]=(dp[i+1][j+2][k]+dp[i][j][k]*c(m-j-k))%mod);(c函数为求(C^2_n)
    4. 在有一个棋子的一列中放棋子,(dp[i+1][j-1][k+1]=(dp[i+1][j-1][k+1]+dp[i][j][k]*j)%mod);
    5. 在有一个棋子的两列放棋子,(dp[i+1][j-2][k+2]=(dp[i+1][j-2][k+2]+dp[i][j][k]*c(j))%mod);
    6. 在有一个棋子的一列和没有棋子的一列放棋子,(dp[i+1][j][k+1]=(dp[i+1][j][k+1]+dp[i][j][k]*(m-j-k)*(j))%mod);
      然后跑个二维求解即可

    附上代码一份

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    int n,m;
    const int mod=9999973;
    ll dp[110][110][110];
    inline int c(int x){
    	  return x*(x-1)/2;	
    }
    int main(){
    	scanf("%d%d",&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(m-j-k>=2)dp[i+1][j+2][k]=(dp[i+1][j+2][k]+dp[i][j][k]*c(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(j>=2)dp[i+1][j-2][k+2]=(dp[i+1][j-2][k+2]+dp[i][j][k]*c(j))%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;
    				}
    			}
    		}
    	}
    	long long ans=0;
    	for(int i=0;i<=m;i++){
    		for(int j=0;j+i<=m;j++){
    			ans=(ans+dp[n][i][j])%mod;
    		}
    	}
    	printf("%lld",ans);
    
    }
    
  • 相关阅读:
    最短路径之迪杰斯特拉算法(Java)
    ipadmini从9.3.5降级8.4.1并完美越狱
    ubuntu中安装VNC供多用户访问(实验室运维踩坑)
    Linux在没有root权限的情况下安装gcc环境
    在WSL中运行32位程序
    将"在此处启动Windows Terminal"添加到右键菜单
    Windows中像在Linux里一样使用CMake和make
    ipadmini iOS8.4.1系统精简
    win10安装ubuntu子系统和xfce4.14图形界面
    FFT快速傅里叶变换
  • 原文地址:https://www.cnblogs.com/soda-ma/p/13229553.html
Copyright © 2020-2023  润新知