洛谷 P2051 [AHOI2009]中国象棋 状态压缩思想DP
题意:
给定一个n*m的空棋盘,问合法放置任意多个炮有多少种情况。合法放置的意思是棋子炮不会相互打到。
思路:
这道题我们可以发现因为炮是隔一个棋子可以打出去,所以每一行每一列最多放置两个炮。
这样子我们就可以试着压缩状态,记录前i行有几列是放一个棋子的,有几列是放两个棋子的,有几列是不放棋子的。
即设dp[ i ][ j ] [ k ] 表示前 i 行,有 j 列是放一个棋子的,有k列是放两个棋子的,有 m - j - k列是不放棋子的。
又由于每行最多可以放两个棋子,所以可以退出第i行和第i-1行的关系。
#include <algorithm>
#include <iterator>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <iomanip>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <stack>
#include <cmath>
#include <queue>
#include <list>
#include <map>
#include <set>
#include <cassert> using namespace std;
#define lson (l , mid , rt << 1)
#define rson (mid + 1 , r , rt << 1 | 1)
#define debug(x) cerr << #x << " = " << x << "\n";
#define pb push_back
#define pq priority_queue typedef long long ll;
typedef unsigned long long ull;
//typedef __int128 bll;
typedef pair<ll ,ll > pll;
typedef pair<int ,int > pii;
typedef pair<int,pii> p3; //priority_queue<int> q;//这是一个大根堆q
//priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q
#define fi first
#define se second
//#define endl '\n' #define OKC ios::sync_with_stdio(false);cin.tie(0)
#define FT(A,B,C) for(int A=B;A <= C;++A) //用来压行
#define REP(i , j , k) for(int i = j ; i < k ; ++i)
#define max3(a,b,c) max(max(a,b), c);
#define min3(a,b,c) min(min(a,b), c);
//priority_queue<int ,vector<int>, greater<int> >que; const ll mos = 0x7FFFFFFF; //
const ll nmos = 0x80000000; //-2147483648
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f; //
const int mod = ;
const double esp = 1e-;
const double PI=acos(-1.0);
const double PHI=0.61803399; //黄金分割点
const double tPHI=0.38196601; template<typename T>
inline T read(T&x){
x=;int f=;char ch=getchar();
while (ch<''||ch>'') f|=(ch=='-'),ch=getchar();
while (ch>=''&&ch<='') x=x*+ch-'',ch=getchar();
return x=f?-x:x;
}
/*-----------------------showtime----------------------*/ const int maxn = ;
ll dp[maxn][maxn][maxn];
ll c[maxn][maxn];
int n,m;
void init(){
c[][] = ;
for(int i=; i<=m; i++){
for(int j=; j<=i; j++){
if(j==) c[i][j] = ;
else if(j==i) c[i][j] = ;
else c[i][j] = (c[i-][j] + c[i-][j-])%mod;
}
}
}
int main(){
scanf("%d%d", &n, &m);
init();
dp[][][] = ;
for(int i=; i<=n; i++){
for(int j=; j<=m; j++){
for(int k=; k<=m-j; k++){ ll tmp = dp[i-][j][k];
if(k>) tmp = tmp + c[j+][] * dp[i-][j+][k-] % mod;
if(k>) tmp = tmp + c[j+][] * dp[i-][j+][k-] % mod;
if(j>) tmp = tmp + c[m-k-j+][] * dp[i-][j-][k] % mod;
if(j>) tmp = tmp + c[m-k-j+][] * dp[i-][j-][k] % mod;
if(k>) tmp = tmp + c[j][] * c[m-j-k+][] * dp[i-][j][k-]%mod;
tmp = tmp % mod;
dp[i][j][k] = tmp % mod;
}
}
}
ll ans = ;
for(int j=; j<=m; j++){
for(int k=; k<=m-j; k++){
ans = (ans + dp[n][j][k]) % mod;
}
}
printf("%lld\n", ans);
return ;
}
洛谷 P2051 [AHOI2009]中国象棋 状态压缩思想DP的更多相关文章
- 洛谷 P2051 [AHOI2009]中国象棋 解题报告
P2051 [AHOI2009]中国象棋 题目描述 这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法. ...
- [洛谷P2051] [AHOI2009]中国象棋
洛谷题目链接:[AHOI2009]中国象棋 题目描述 这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法 ...
- 洛谷 P2051 [AHOI2009]中国象棋
题目描述 这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法.大家肯定很清楚,在中国象棋中炮的行走方式是 ...
- 洛谷P2051 [AHOI2009] 中国象棋(状压dp)
题目简介 n*m的棋盘,对每行放炮,要求每行每列炮数<=2,求方案数%9999973 N,M<=100 题目分析 算法考虑 考虑到N,M范围较小,每一行状态只与前面的行状态有关,考虑状压D ...
- 洛谷P2051 [AHOI2009]中国象棋(dp)
题面 luogu 题解 \(50pts:\)显然是\(3\)进制状压\(dp\) \(100pts:\) 一行一行地考虑 \(f[i][j][k]\)表示前\(i\)行,有\(j\)列放了一个,有\( ...
- [Luogu P2051] [AHOI2009]中国象棋 (状压DP->网格DP)
题面 传送门:https://www.luogu.org/problemnew/show/P2051 Solution 看到这题,我们不妨先看一下数据范围 30pt:n,m<=6 显然搜索,直接 ...
- BZOJ1801或洛谷2051 [AHOI2009]中国象棋
BZOJ原题链接 洛谷原题链接 这题挺难想状态的,刚看题感觉是状压,但数据\(100\)显然不可能. 注意到每行每列只能放\(0\sim 2\)个棋子,所以我们可以将这个写入状态. 设\(f[i][j ...
- 洛谷.2051.[AHOI2009]中国象棋(DP)
题目链接 /* 每行每列不能超过2个棋子,求方案数 前面行对后面行的影响只有 放了0个.1个.2个 棋子的列数,与排列方式无关 所以设f[i][j][k]表示前i行,放了0个棋子的有j列,放了1个棋子 ...
- 洛谷2051 [AHOI2009]中国象棋
题目链接 题意概述:n行m列棋盘放若干个棋子每行每列最多两个求方案总数,答案对9999973取模. 可以比较容易看出这是个dp,设f[i][j][k]表示前i行j列放1个棋子k列放2个棋子的方案总数. ...
随机推荐
- 从深处去掌握数据校验@Valid的作用(级联校验)
每篇一句 NBA里有两大笑话:一是科比没天赋,二是詹姆斯没技术 相关阅读 [小家Java]深入了解数据校验:Java Bean Validation 2.0(JSR303.JSR349.JSR380) ...
- CoreCLR Host源码分析(C++)
废话不多说,直接上源码: 1.在托管程序集里面执行方法 HRESULT CorHost2::ExecuteAssembly(DWORD dwAppDomainId,//通过CreateAppDomai ...
- go 学习笔记之工作空间
搭建好 Go 的基本环境后,现在可以正式开始 Go 语言的学习之旅,初学时建议在默认的 GOPATH 工作空间规范编写代码,基本目录结构大概是这个样子. . |-- bin | `-- hello.e ...
- java基础知识总结,绝对经典
写代码: 1,明确需求.我要做什么? 2,分析思路.我要怎么做?1,2,3. 3,确定步骤.每一个思路部分用到哪些语句,方法,和对象. 4,代码实现.用具体的java语言代码把思路体现出来. 学习新技 ...
- mysql新增一列为主键
mysql新增一列为主键 由于一次疏忽在建表的时候忘记加上主键了, 但是目前来说表里面又有数据了,所以不能删表重建,所以需要新加一列主键 然后我就新加一列,并且为auto_increment,然后设置 ...
- 本地NTP服务器与客户端配置
1. NTP 简介 NTP是网络时间协议(Network Time Protocol),它是用来同步网络中各个计算机的时间的协议. 在集群中,为了保证各节点之间的时间一致,我们通常需要配置本地的 NT ...
- 使用阿里云oss
写这篇博文的原因是公司有个项目需要用到阿里云来存放用户头像文件.后期软件安装版本也可能需要存进去,然后折腾了两天终于摸熟了一点皮毛,在这里给大家简单介绍下. 一.初识对象存储oss 1.进入阿里云控制 ...
- android ——Toolbar
Toolbar是我看material design内容的第一个 官方文档:https://developer.android.com/reference/android/support/v7/widg ...
- struts的上传下载
文件上传 添加jar包 commons-io-1.3.2.jar commons-fileupload-1.2.1.jar 前台页面 form表单 method值为post 添加"encty ...
- Java 安全之:csrf攻击总结
最近在维护一些老项目,调试时发现请求屡屡被拒绝,仔细看了一下项目的源码,发现有csrf token校验,借这个机会把csrf攻击学习了一下,总结成文.本文主要总结什么是csrf攻击以及有哪些方法来防范 ...