题目简介

n*m的棋盘,对每行放炮,要求每行每列炮数<=2,求方案数%9999973 N,M<=100

题目分析

算法考虑

考虑到N,M范围较小,每一行状态只与前面的行状态有关,考虑状压Dp

算法分析

设dp[i][j][k]表示放了前i行,j列有1个棋子,k列有两个棋子

那么0个棋子就是m-j-k

然后就可以分类讨论了

情况一

第i行不放棋子:直接继承上一行状态,有:f[i][j][k]=f[i-1][j][k]

情况二

第i行只放一个棋子:

1、该棋放在只有一个棋的列上

有f[i][j][k]=f[i-1][j+1][k-1]*(j+1) 因为对于前i-1行,有一个棋子的一列少了1,而因为放置棋子,有两个的棋子又多了一列,又因为该棋子可以随便放在只有一个棋的列上,所以要乘(j+1)

有:f[i][j][k]=f[i-1][j+1][k-1]*(j+1)

2、该棋放在没有棋子的列上

同理,即f[i-1][j-1][k]可以转移到f[i][j][k]

又因为我在空列中的任何一列放置这个棋子.

所以要×(m-j-k+1)

有:f[i][j][k]=f[i][j][k]+f[i-1][j-1][k]*(m-j-k+1);

情况三

第i行放两个棋子

1、放在一列一个的,一列没有棋子的列上

一个没有棋子的列会变成一个有一个棋子的列,而一个有一个棋子的列会变成一个有两个棋子的列。

此时我们发现,

有一个棋子的列的数量不会变,因此第二维依旧为j,

又因为我们会新增一个有两个棋子的列,所以我们需要从k-1转移过来.

有:f[i][j][k]=f[i][j][k]+f[i-1][j][k-1]*j*(m-j-k+1)

2、放在两个没有棋子的列上

会增加两个新的有一个棋子的列.

因此我们需要从j-2转移过来.

而两个棋子的列的数量并不会改变,所以依旧为k

最后乘C(2,m-k-j+2),因为从没有棋子的列中任选两个

有:f[i][j][k]=f[i][j][k]+f[i-1][j-2][k]*C(2,m-k-j+2)

3、放在两个有一个棋子的列上

这两个有一个棋子的列都会变成有两个子的列.

即j+2变成j,从k-2变成k

最后乘C(2,j+2)因为从有一个棋子的列中任选两个

有:f[i][j][k]=f[i][j][k]+f[i-1][j+2][k-2]*C(2,j+2)

代码

#include<bits/stdc++.h>
#define re register
#define ll long long
using namespace std;
inline int read()
{
int k=1,sum=0;
char c=getchar();
for(;c<'0' || c>'9';c=getchar()) if(c=='-') k=-1;
for(;c>='0' && c<='9';c=getchar()) sum=sum*10+c-'0';
return sum*k;
}
int n,m;
const int MOD=9999973,N=1e2+10;
ll f[N][N][N];
inline int C(int x){
return ((x*(x-1))/2)%MOD;
}
int main()
{
n=read();m=read();f[0][0][0]=1;
for(re int i=1;i<=n;++i){
for(re int j=0;j<=m;++j){
for(re int k=0;k<=m-j;++k){
f[i][j][k]=f[i-1][j][k];
if(k>0 && j+1<=m) f[i][j][k]=(f[i][j][k]+f[i-1][j+1][k-1]*(j+1))%MOD;
if(j>0) f[i][j][k]=(f[i][j][k]+f[i-1][j-1][k]*(m-j-k+1))%MOD;
if(k>0) f[i][j][k]=(f[i][j][k]+f[i-1][j][k-1]*j*(m-j-k+1))%MOD;
if(k>1) f[i][j][k]=(f[i][j][k]+f[i-1][j+2][k-2]*C(j+2))%MOD;
if(j>1) f[i][j][k]=(f[i][j][k]+f[i-1][j-2][k]*C(m-k-j+2))%MOD;
f[i][j][k]%=MOD;
}
}
}
int ans=0;
for(re int j=0;j<=m;++j)
for(re int k=0;k<=m-j;++k)
ans=(ans+f[n][j][k])%MOD;
cout<<ans;
return 0;
}

洛谷P2051 [AHOI2009] 中国象棋(状压dp)的更多相关文章

  1. 洛谷 P2051 [AHOI2009]中国象棋 解题报告

    P2051 [AHOI2009]中国象棋 题目描述 这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法. ...

  2. [Luogu P2051] [AHOI2009]中国象棋 (状压DP->网格DP)

    题面 传送门:https://www.luogu.org/problemnew/show/P2051 Solution 看到这题,我们不妨先看一下数据范围 30pt:n,m<=6 显然搜索,直接 ...

  3. 洛谷 P2051 [AHOI2009]中国象棋 状态压缩思想DP

    P2051 [AHOI2009]中国象棋 题意: 给定一个n*m的空棋盘,问合法放置任意多个炮有多少种情况.合法放置的意思是棋子炮不会相互打到. 思路: 这道题我们可以发现因为炮是隔一个棋子可以打出去 ...

  4. [洛谷P2051] [AHOI2009]中国象棋

    洛谷题目链接:[AHOI2009]中国象棋 题目描述 这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法 ...

  5. 洛谷P2051 [AHOI2009]中国象棋(dp)

    题面 luogu 题解 \(50pts:\)显然是\(3\)进制状压\(dp\) \(100pts:\) 一行一行地考虑 \(f[i][j][k]\)表示前\(i\)行,有\(j\)列放了一个,有\( ...

  6. 洛谷 P2051 [AHOI2009]中国象棋

    题目描述 这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法.大家肯定很清楚,在中国象棋中炮的行走方式是 ...

  7. 【题解】洛谷P3959 [NOIP2017TG] 宝藏(状压DP+DFS)

    洛谷P3959:https://www.luogu.org/problemnew/show/P3959 前言 NOIP2017时还很弱(现在也很弱 看出来是DP 但是并不会状压DP 现在看来思路并不复 ...

  8. 洛谷 P1278 单词游戏 【状压dp】

    题目描述 Io和Ao在玩一个单词游戏. 他们轮流说出一个仅包含元音字母的单词,并且后一个单词的第一个字母必须与前一个单词的最后一个字母一致. 游戏可以从任何一个单词开始. 任何单词禁止说两遍,游戏中只 ...

  9. 洛谷P2704 [NOI2001]炮兵阵地 [状压DP]

    题目传送门 炮兵阵地 题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图 ...

随机推荐

  1. 我真的不想再用 JPA 了

    在开发者的圈子里,没当说到一种技术好或者不好,都会引发激烈或者不激烈的争论,直到一个开发者出来说 PHP 是世界上最好的语言,大家伙儿才会纷纷退去继续写代码. 今天说 JPA 的问题不是想引发什么讨论 ...

  2. BMP 图像信息隐藏及检测

    原理简介 针对文件结构的信息隐藏方法需详细掌握文件的格式,利用文件结构块之间的关系或根据块数据和块大小之间的关系来隐藏信息. BMP(Bitmap-File)图形文件是 Windows 采用的常见图形 ...

  3. Salesforce学习之路-admin篇

    Salesforce是一款非常强大的CRM(Customer Relationship Management)系统,国外企业使用十分频繁,而国内目前仅有几家在使用(当然,国内外企使用的依旧较多),因此 ...

  4. tlc549

    #include <reg51.h> #include "TLC549.c" code uchar seven_seg[] = {0xc0, 0xf9, 0xa4, 0 ...

  5. 42 (OC)* 字典实现原理--哈希原理

    一.NSDictionary使用原理 1.NSDictionary(字典)是使用 hash表来实现key和value之间的映射和存储的,hash函数设计的好坏影响着数据的查找访问效率. - (void ...

  6. 大白话讲解 Java程序的运行机制和JVM

    据我们所知,Java程序是跨平台的.那么Java是如何实现跨平台的呢?看完下面几句话就会恍然大悟! 1.为什么Java语言既是编译型语言又是解释型语言呢? 答:运行Java程序,首先需要经过编译,编译 ...

  7. thinkphp 多条件模糊搜索结果,按照最佳匹配度排序,使用LOCATE函数

    //获取筛选参数 $params = Request()->only(['keywords','brand_id', 'cat_id']); $where = "brand_id = ...

  8. Linux下一键安装包的基础上安装SVN及实现nginx web同步更新

    Linux下一键安装包的基础上安装SVN及实现nginx web同步更新 一.安装 1.查看是否安装cvs rpm -qa | grep subversion 2.安装 yum install sub ...

  9. 在wxml中直接写js代码(wxs)

    我们在h5开发中,很多时候要在html中写到js代码,这个很容易实现.但是在微信小程序开发中,是不能直接在wxml中写js代码的,因此就有了wxs.在wxml中用wxs代码,有以下几种方式(在小程序文 ...

  10. 读取unicode日志文件并清除记录的垃圾文件

    //读取unicode文件,并清除记录的垃圾文件 //参数1:日志文件路径 bool ReadFilePath(const wchar_t *DataFilePath) { wchar_t ChBuf ...