题目链接

题目描述

在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法。
(在中国象棋中炮的行走方式是:一个炮攻击到另一个炮,当且仅当它们在同一行或同一列中,且它们之间恰好 有一个棋子。)

输入输出格式

输入格式:

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

输出格式:

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

样例

输入样例 输出样例
1 3 7

思路

1. 30分做法

dfs,复杂度玄学

没有代码

2.50分做法

分析题目
当满足题意下,每行每列有且最多只有两个炮
注意题目保证行或列小于等于8
考虑dp 按行或列转移(假设按行转移,即n<=8)
如果知道了考虑到当前行时,每列已经放了的棋子个数
那么当前行放棋子的方案就能够确定(每行最多放两个)
那么如果会状压的同学应该已经会了 (逃
定义dp[n][4^m]表示当考虑到第n行时,之前所放的棋子状态为2^2m时的方案数
通过两位二进制表示一列的状态 00代表没有放棋子 01代表放了一个棋子 11代表不能再放棋子
然后转移就可以了

没有代码

3.满分做法

考虑dp转移过程

  • 不选
  • 选00->01
  • 选01->11
  • 选00,00->01,01
  • 选00,01->01,11
  • 选01,01->11,11

如果你发现,转移并不用知道每一列究竟放了几个棋子的话...
定义dp[n][i][j]表示当考虑到第n行时,没有放棋子的有i列,放了一个棋子的有j列

定义C(x,y)为在x中取y个的方案数
那么上面的转移过程表示出来就是

  • C(i+j,0)
  • C(i,1)
  • C(j,1)
  • C(i,2)
  • C(i,1)*C(j,1)
  • C(j,2)

假设现在取了 00,01
那么就有 dp[n+1][i-1][j-1]=dp[n][i][j]*C(i,1)*C(j,1)

有代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define rint register int
#define ci const int&
#define ll long long
using namespace std;const int mod=9999973;
ll dp[101][102][102];
int n,m;
ll ans=0;int main(){cin>>n>>m;//初始化,在第0行,放了1个的列为0(即01为0),放了0个的列为m(即00为m)的情况数有一种 dp[0][0][m]=1;for(rint i=0;i<n;i++)for(rint j=0;j<=m;j++)for(rint k=0;k<=m-j;k++)if(dp[i][j][k]){//如果状态可到达 if(k){//当00数>=1时 if(j)dp[i+1][j][k-1]+=dp[i][j][k]*k*j,dp[i+1][j][k-1]%=mod;//当01数>=1时,选00,01放置 dp[i+1][j+1][k-1]+=dp[i][j][k]*k;dp[i+1][j+1][k-1]%=mod;//选00放置 if(k>1)dp[i+1][j+2][k-2]+=dp[i][j][k]*k*(k-1)/2,dp[i+1][j+2][k-2]%=mod;//当00数>=2时,选00,00放置 }if(j){//当01数>=1时 dp[i+1][j-1][k]+=dp[i][j][k]*j;dp[i+1][j-1][k]%=mod;//选01放置 if(j>1)dp[i+1][j-2][k]+=dp[i][j][k]*j*(j-1)/2,dp[i+1][j-2][k]%=mod;//当01数>=2时,选01,01放置 }dp[i+1][j][k]+=dp[i][j][k];dp[i+1][j][k]%=mod;//不放 }for(rint j=0;j<=m;j++)for(rint k=0;k<=m-j;k++)if(dp[n][j][k])(ans+=dp[n][j][k])%=mod;//统计 cout<<ans;//dp数组用long long,中间存在乘法,极限情况下会爆int,亲身试验....
}

转载于:https://www.cnblogs.com/ullio/p/9369323.html

AHOI2009 中国象棋相关推荐

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

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

  2. BZOJ 1801 [Ahoi2009]中国象棋(线性动规)(洛谷P2051)

    题意:就是在n*m的格子中放"炮"(中国象棋中的棋子)问有多少种放法,使得没有任意的两个炮相互攻击 思路:我们很容易的得到一列或者一行中最多放下两个炮(我也只能得到这些了,满脑子状 ...

  3. LG_2051_[AHOI2009]中国象棋

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

  4. 【洛谷 P2051】 [AHOI2009]中国象棋(DP)

    题目链接 首先想到状压dp,但是\(n,m\)高达100,怎么压? 容易发现,每行每列最多两个象棋,否则就直接gg了. 一个巧妙的设置状态的方式是,只需要记录到当前行有多少列是放了1个炮和2个炮. 然 ...

  5. 洛谷2051 [AHOI2009]中国象棋

    题目链接 题意概述:n行m列棋盘放若干个棋子每行每列最多两个求方案总数,答案对9999973取模. 可以比较容易看出这是个dp,设f[i][j][k]表示前i行j列放1个棋子k列放2个棋子的方案总数. ...

  6. [AHOI2009]中国象棋

    https://www.luogu.org/problemnew/show/P2051 C++版本一 数位DP变形 棋子的顺序是无所谓的,并不需要准确知道当前棋盘的状态 于是有了100分做法:dp[i ...

  7. 洛谷 - P2051 [AHOI2009]中国象棋(计数dp)

    题目链接:点击查看 题目大意:给出一个 n * m 的棋盘,可以在任意位置放置 "炮",问一共可以放置多少种可行的方案 题目分析:转换题意,就是问每一行.每一列至多有两个棋子的方案 ...

  8. P2051 [AHOI2009]中国象棋

    题目链接 题目大意: 给定n*m大小表格,让你摆放棋子,摆放的要求是同一行.同一列中的棋子数不超过两个,问一共可能有多少摆法. (不看别人的题解真不会开dp数组,太弱小了) dp数组开三位,表示已经处 ...

  9. BZOJ1801: [Ahoi2009]chess 中国象棋

    BZOJ1801: [Ahoi2009]chess 中国象棋 Description 在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮. 请问有多少种放置方法,中国像棋中炮 ...

最新文章

  1. spark调优(一)-开发调优,数据倾斜,shuffle调优
  2. jesd204b应用指南中文_Novation 发布 Summit 合成器中文用户指南
  3. leetcode算法题--零钱兑换
  4. 通向高可扩展性之路(谷歌篇)
  5. Excel中删除链接
  6. [网站搭建] 阿里云虚拟主机搭建及FTP文件上传
  7. python爬虫深入爬取_Python爬虫初学(一)—— 爬取段子
  8. 怎样修改iis 服务器日期,怎么在IIS里设置服务器端缓存时间?
  9. Maven精选系列--私库搭建及使用
  10. centos6 yum快速安装mysql_centos6.10 yum安装mysql 5.6-Go语言中文社区
  11. win10关机后自动重启_win10电脑关机后自动开机怎么解决
  12. java读取合并单元格_Java POI常用方法,读取单元格的值,设置单元格格式,合并单元格,获取已合并的单元格,导出至本地等...
  13. 在线扒站工具, 扒站网站工具(简单、快捷、免费)
  14. 关于文本分类(情感分析)的英文数据集汇总
  15. 《暗时间》读书笔记与读后感
  16. 百度云盘Mac破解不限制下载速度-百度网盘客户端 - Go语言编写
  17. 免费开放,GSTO-沪深A股L2行情数据API接口,开发接口文档
  18. 动态规划之二项式系数
  19. vue实现下拉表单二级联动
  20. 首批 | 易知微加入“新华网元宇宙及 AIGC 创新联盟”,探索AIGC数字人深度应用

热门文章

  1. html元素li移动动态效果
  2. ListView分页
  3. [译]WCF RIA Services中的集合(2)
  4. 基于Visual Studio2010讲解C#4.0语法(5)--使用CollectionClasses
  5. Openstack虚机实例状态错误手工恢复vm_state:error
  6. python之 启动一个子进程并等待其结束
  7. Chisel_LLDB调试命令
  8. 基于人脸识别的商业大数据13
  9. 查看windows系统当前使用的字符集
  10. android中使用DisplayMetrics获取屏幕参数