AHOI2009中国象棋
首先以行为阶段,根据象棋的规则,在同一行中,至多只能有两个炮,同理:在同一列中,至多只能有两个炮
思考一个可以覆盖整个状态空间的dp数组:
dp[i]表示到了第i行
接下来我们想:某列中的炮能否通过位运算求得
我们能够发现,可能我们目前在第i行,但是在某个j行的p列有一个炮,我们要知道第i行的第p列能否放置炮。但是j可能与i相差甚远,我们不能直接通过位运算得到,逐行枚举又会耗费大量不必要的时间。
那么我们就干脆将列的状态记录在数组里,我们想我们其实并不关心到第i行时哪一列有1个炮,哪一列有两个炮,我们只需要知道到第i行时,有多少列有1个炮,有多少列有两个炮,剩下的问题我们能够通过枚举状态解决
这样就有了dp数组:
dp[i][j][k]表示到第i行时,有j列有一个炮,k列有两个炮
假设第i行只放一个炮,那么放置的方法数累加(DP方程)就是:
1.这一个炮放在了原来没有炮的位置
dp[i][j][k] += dp[i - 1][j - 1][k] * (m - j - k)
2.这一个炮放在了原来有一个炮的位置
dp[i][j][k] += dp[i - 1][j + 1][k - 1] * j
假设第i行放置了两个炮
1.这一行两个炮都放在了原来没有炮的位置
dp[i][j][k] += dp[i - 1][j - 2][k] * (m - j - k) * (m - j - k - 1) / 2;
2.这一行一个炮放在了原来有一个炮的位置,一个炮放在了原来没有炮的位置
dp[i][j][k] += dp[i - 1][j][k - 1] * (m - j - k) * j
3.这一行的两个炮都放在了原来有一个炮的位置
dp[i][j][k] += dp[i - 1][j + 2][k - 2] * j * (j - 1) / 2;
假设第i行没有放炮
dp[i][j][k] += dp[i - 1][j][k]
=-=??好像没了?接着就是处理一下每种情况能够使用的限制条件
初态:dp[0][0][0] = 1;
末态:Σdp[n][i][j]
恩是的,这是我原本的思路,但我这么写后,不知道为什么就挂了。
挂了!样例都过不了!
于是我毅然决然的把有前驱推当前状态的写法改为了由当前状态推后继状态,然后就...A了.....
方程差别不大,不做修改,直接看代码吧...
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int p = ;
const int maxn = ;
ll f[maxn][maxn][maxn];
int n, m; inline int read() {
int x = , y = ;
char ch = getchar();
while(!isdigit(ch)) {
if(ch == '-') y = -;
ch = getchar();
}
while(isdigit(ch)) {
x = (x << ) + (x << ) + ch - '';
ch = getchar();
}
return x * y;
} inline int count(int k) {
return k * (k - ) / ;} int main() {
memset(f, , sizeof(f));
n = read(), m = read();
f[][][] = ;
for(int i = ; i < n; ++i)
for(int j = ; j <= m; ++j)
for(int k = ; k + j <= m; ++k)
if(f[i][j][k]) {
f[i + ][j][k] = (f[i][j][k] + f[i + ][j][k]) % p;
if(m - j - k >= ) f[i + ][j + ][k] = (f[i + ][j + ][k] + f[i][j][k] * (m - j - k)) % p;
if(j >= ) f[i + ][j - ][k + ] = (f[i + ][j - ][k + ] + f[i][j][k] * j) % p;
if(m - j - k >= ) f[i + ][j + ][k] = (f[i + ][j + ][k] + f[i][j][k] * count(m - j - k)) % p;
if(m - j - k >= && j >= ) f[i + ][j][k + ] = (f[i + ][j][k + ] + f[i][j][k] * (m - j - k) * j) % p;
if(j >= ) f[i + ][j - ][k + ] = (f[i + ][j - ][k + ] + f[i][j][k] * count(j)) % p;
f[i][j][k] %= p;
}
ll ans = ;
for(int i = ; i <= m; ++i)
for(int j = ; j + i <= m; ++j)
ans = (ans + f[n][i][j]) % p;
cout << ans << '\n';
return ;
}
AHOI2009中国象棋的更多相关文章
- 洛谷 P2051 [AHOI2009]中国象棋 解题报告
P2051 [AHOI2009]中国象棋 题目描述 这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法. ...
- luogu 2051 [AHOI2009]中国象棋
luogu 2051 [AHOI2009]中国象棋 真是一道令人愉♂悦丧心并框的好题... 首先"没有一个炮可以攻击到另一个炮"有个充分条件就是没有三个炮在同一行或同一列.证明:显 ...
- [洛谷P2051] [AHOI2009]中国象棋
洛谷题目链接:[AHOI2009]中国象棋 题目描述 这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法 ...
- 洛谷 P2051 [AHOI2009]中国象棋 状态压缩思想DP
P2051 [AHOI2009]中国象棋 题意: 给定一个n*m的空棋盘,问合法放置任意多个炮有多少种情况.合法放置的意思是棋子炮不会相互打到. 思路: 这道题我们可以发现因为炮是隔一个棋子可以打出去 ...
- Luogu P2051 [AHOI2009]中国象棋(dp)
P2051 [AHOI2009]中国象棋 题面 题目描述 这次小可可想解决的难题和中国象棋有关,在一个 \(N\) 行 \(M\) 列的棋盘上,让你放若干个炮(可以是 \(0\) 个),使得没有一个炮 ...
- [Luogu P2051] [AHOI2009]中国象棋 (状压DP->网格DP)
题面 传送门:https://www.luogu.org/problemnew/show/P2051 Solution 看到这题,我们不妨先看一下数据范围 30pt:n,m<=6 显然搜索,直接 ...
- P2051 [AHOI2009]中国象棋
题目描述 这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法.大家肯定很清楚,在中国象棋中炮的行走方式是 ...
- [AHOI2009]中国象棋
题目描述 这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法.大家肯定很清楚,在中国象棋中炮的行走方式是 ...
- [P2051 [AHOI2009]中国象棋] DP
https://www.luogu.org/problemnew/show/P2051 题目描述 这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一 ...
- BZOJ1801:[AHOI2009]中国象棋——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=1801 https://www.luogu.org/problemnew/show/P2051 这次小 ...
随机推荐
- hdu6103 Kirinriki(trick+字符串)
题解: 考虑一开始时,左边从1开始枚举,右边从n开始枚举 我们可以得到一个最大的值k. 但是如果这样依次枚举,复杂度肯定是n^3,是不行的 考虑如何利用上一次的结果,如果我们把1和n同时去掉 就可以利 ...
- BZOJ3289 Mato的文件管理 【莫队 + 树状数组】
3289: Mato的文件管理 Time Limit: 40 Sec Memory Limit: 128 MB Submit: 3964 Solved: 1613 [Submit][Status] ...
- 【BZOJ 3772】精神污染 主席树+欧拉序
这道题的内存…………………真·精神污染……….. 这道题的思路很明了,我们就是要找每一个路径包含了多少其他路径那么就是找,有多少路径的左右端点都在这条路径上,对于每一条路径,我们随便选定一个端点作为第 ...
- echarts中图表过于靠左或靠右的情况解决办法。
经过好多次尝试,终于在http://blog.csdn.net/ainuser/article/details/76641963中得到解决. grid: { x: '30%', //相当于距离左边效果 ...
- BS架构下使用消息队列的工作流程
异步通信 对于BS(Browser-Server 浏览器)架构,很多情景下server的处理时间较长. 如果浏览器发送请求后,保持跟server的连接,等待server响应,那么一方面会对用户的体验有 ...
- tomcat内存配置(二)
Tomcat本身不能直接在计算机上运行,需要依赖于硬件基础之上的操作系统和一个Java虚拟机.Tomcat的内存溢出本质就是JVM内存溢出,所以在本文开始时,应该先对JavaJVM有关内存方面的知识进 ...
- 1、linux下mysql5.5.20安装过程报错汇总
1.Access denied for user 'root'@'localhost' (using password: YES) 这个提示是因为root帐户默认不开放远程访问权限,所以需要修改一下相 ...
- eclipse console输出有长度限制
抓取一个网页内容,然后打印到控制台,发现内容首部都没有了. String content = getResponseText("http://xxx.html"); System. ...
- webpack 引入 html-webpack-plugin 报错
配置webpack当中,出现一个问题: 引入html-webpack-plugin 插件报错. 这时需要本地(也就是当前项目下)安装一下webpack就可以解决问题了. 注意:现在是webpack4版 ...
- ES6学习笔记(五)—— 编程风格
1. 块级作用域 let 取代 var —— let 只在声明的代码块内有效,而且不存在变量提升的效用 const 取代 let —— const 比较符合函数式编程的思想,运算不改变值,只是新建值: ...