BZOJ 1801 chess 中国象棋
题意:
在n * m 的棋盘上放"炮",使得任意两个炮都不会互相攻击,求方案数。
题解:
既然是求方案数,那么考虑数学方法和递推,这一道题的限制条件比较麻烦,数学方法不合适,考虑递推。
现在考虑定义状态,很显然一维需要行数,表示考虑了前i行,现在在第i行放棋子,需要明白的是每一行每一列最多放两个炮,那么放棋子是有限制条件的,也就是每一列的已经放了的棋子数目在限制当前的放法,那么我们需要再开三维表示,没放棋子的列数,放一个棋子的列数,放两个棋子的列数,仔细一想没放棋子的列数可以通过后两个计算出来,并且第一维也可以滚动起来。
那么转移也变得很显然了。
1.第i行不放棋子。
2.第i行只放一个棋子 : ①放在没放棋子的那一列 ②放在放了一个棋子的那一列
3.第i行放两个棋子: ①全都放在没放棋子的列上 ②分别放在没放棋子的列和放了一个棋子的列上 ③全都放在放了一个棋子的列上
代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;#define ll long long
const int N = 1e2 + 7;
const int mod = 9999973;
int n, m;
ll dp[N][N][N];int calc (int x) {return x * (x - 1) / 2;
}int main () {scanf ("%d%d", &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; ++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 (j >= 2) dp[i][j][k] += dp[i - 1][j - 2][k] * calc(m - k - j + 2);if (k >= 1 && j <= m - 1) dp[i][j][k] += dp[i - 1][j + 1][k - 1] * (j + 1);if (k >= 2 && j <= m - 2) dp[i][j][k] += dp[i - 1][j + 2][k - 2] * calc(j + 2);if (k >= 1) dp[i][j][k] += dp[i - 1][j][k - 1] * (m - k - j + 1) * j;dp[i][j][k] %= mod;}}}ll ret = 0;for (int j = 0; j <= m; ++j) for (int k = 0; k <= m; ++k) ret = (ret + dp[n][j][k]) % mod;cout << ret << endl;return 0;
}
转载于:https://www.cnblogs.com/xgtao/p/5991072.html
BZOJ 1801 chess 中国象棋相关推荐
- BZOJ 1801 [Ahoi2009]中国象棋(线性动规)(洛谷P2051)
题意:就是在n*m的格子中放"炮"(中国象棋中的棋子)问有多少种放法,使得没有任意的两个炮相互攻击 思路:我们很容易的得到一列或者一行中最多放下两个炮(我也只能得到这些了,满脑子状 ...
- BZOJ 1801: [Ahoi2009]chess 中国象棋( dp )
dp(i, j, k)表示考虑了前i行, 放了0个炮的有j列, 放了1个炮的有k列. 时间复杂度O(NM^2) -------------------------------------------- ...
- bzoj 1801: [Ahoi2009]chess 中国象棋 bzoj 4806: 炮
1801: [Ahoi2009]chess 中国象棋 Time Limit: 10 Sec Memory Limit: 64 MB Submit: 1851 Solved: 1062 [Submi ...
- BZOJ1801: [Ahoi2009]chess 中国象棋
BZOJ1801: [Ahoi2009]chess 中国象棋 Description 在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮. 请问有多少种放置方法,中国像棋中炮 ...
- bzoj 1801: [Ahoi2009]chess 中国象棋【dp】
注意到一行只能放012个炮,我们只需要知道列的状态,不用状压行 所以设f[i][j][k]表示前i行有j列有1个炮,有k列有2个炮的方案数 然后分情况讨论转移就行了 #include<cstdi ...
- BZOJ 1801 AHOI 2009 chess 中国象棋 DP
题目大意:给出棋盘的大小,问任意行和列放置的棋子都不超过两个有多少种方案. 思路:一个比较麻烦的DP.f[i][j][k]表示到前i行,放置了一个棋子的列为j,放置了两个棋子的列为k的方案数,然后有六 ...
- 【BZOJ1801】【DTOJ2004】 [Ahoi2009]chess 中国象棋 【DP】
题解: 首先知道一个性质,每一行每一列都最多有两个炮 那么很显然是DP 设F[i][j][k]表示前i行,有j列有一个炮,有k列有两个炮,那么转移式子为 这一行什么都不做:f[i][j][k]=f[i ...
- 2017.10.23 chess 中国象棋 思考记录
这种题的一般解法: 1. 发现状压可以搞,然后发现状态爆炸 2.考虑状态特点,一共只有几种可能的状态 3.考虑可不可以只对状态进行计数 4.离散统计贡献 码: #include<iostream ...
- [AHOI 2009]chess 中国象棋
Description 题库链接 给你一张 \(N\times M\) 的棋盘.要求每行每列最多放两个棋子,问总方案数. \(1\leq N,M\leq 100\) Solution 记 \(f_{i ...
最新文章
- Python-str函数
- 数据结构和算法分析:第一章 引论
- Vue.js指令实例
- oracle数据block默认是,oracleBLOCK(数据块)
- HttpClinet学习笔记
- Rds基于mysql开发的_开发云数据库RDS MYSQL版讲解
- C语言 printf函数实现
- A股开盘:深证区块链50指数涨0.94%,*ST晨鑫涨停
- Channel shutdown: channel error; protocol method
- java与jsp的关系_浅谈servlet与jsp的关系
- 利用IS61LV12816实现DSP28335的内存扩展
- 三菱J4伺服驱动器拨码
- 3ds max软件如何彻底卸载干净
- 【Hive】Establishing SSL connection without server‘s identity verification is not recommended. Accord
- 什么是高中物理?一篇长长长长文告诉你!
- Python - 列表补充(二)
- java实现 xls转xlsx
- 1 什么叫多媒体计算机,选择1多媒体计算机中的媒体信息是指()文字声音.ppt
- char c1,c2;与int c1,c2是否无条件地等价.cpp
- Jmeter 压测工具
热门文章
- C语言 makefile
- 数据算法之二叉树插入(BinaryTreeL Insert)的Java实现
- Java折叠_[Java教程]Jquery中菜单的展开和折叠
- word vba 点击任意域代码,刷新整个文档的域代码值
- 九种分布式ID生成方式
- 计算机行业深度分析,广发证券计算机行业深度分析
- php 时间戳存储 原因,将php文件中的unix时间戳存储到mysql中(store unix timestamp from php file into mysql)...
- java学生奖学金管理系统_EasyUI+JavaWeb奖助学金管理系统[6]-登录功能实现
- 雷军定AI+IoT为小米核心战略,牵手宜家推进生态布局
- 【邀请函】第十届中国电子政务高峰论坛即将开幕