题目链接:传送门

题目大意:

  在N行M列的棋盘中放象棋中的“炮”,问要使得“炮”两两互不伤害,有多少种放法。

  1 ≤ n,m ≤ 100,答案对9999973取模。

思路:

  按行更新答案。每行炮可以放在空列(下称A列)和有一个炮的列(下称B列),从而生成B列和有两个炮的列(C列),所以更新行的时候有这样几种选择:

①不放“炮”;

②选一个A列放一个“炮”,生成一个B列;

③选一个B列放一个“炮”,生成一个C列;

④选两个A列放一个“炮”,生成两个B列;

⑤选两个B列放一个“炮”,生成两个C列;

⑥选一个A列和一个B列各放一个“炮”,生成一个B列和一个C列;(注意在同一行不能放两个棋子在同一列,所以不能看作用一个A列生成一个C列)

考虑到各行各列的顺序与答案无关:

状态:

  f[i][j][k]:第i行有j个B列和k个C列。

初始状态:

  f[0][0][0] = 1;

状态转移方程:

  ①f[i][j][k] = f[i-1][j][k];

  ②f[i][j][k] = f[i-1][j-1][k] ×(i-1行A列个数);

  ③f[i][j][k] = f[i-1][j+1][k-1] ×(i-1行B列个数);

  ④f[i][j][k] = f[i-1][j-2][k] ×(i-1行A列个数选2);

  ⑤f[i][j][k] = f[i-1][j+2][k-2] ×(i-1行B列个数选2);

  ⑥f[i][j][k] = f[i-1][j][k-1] ×(i-1行A列个数)×(i-1行B列个数);

注意边界和取模即可。

时间复杂度:O(nm2)

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int MAX_N = ;
const int MOD = ; ll f[MAX_N][MAX_N][MAX_N]; inline int C(int n)
{//n选2
return n*(n-)/;
} int main()
{
int N, M;
cin >> N >> M;
f[][][] = ;
for (int i = ; i <= N; i++) {
for (int j = ; j <= M; j++) {
for (int k = ; k+j <= M; k++) {
//放1个
if (j- >= && (M-(j-+k)) >= )
f[i][j][k] = (f[i][j][k] + f[i-][j-][k] * (M-(j-+k))) % MOD;
if (j+ <= M && k >= )
f[i][j][k] = (f[i][j][k] + f[i-][j+][k-] * (j+)) % MOD;
//放两个
if (j- >= && (M-(j-+k)) >= )
f[i][j][k] = (f[i][j][k] + f[i-][j-][k] * C(M-(j-+k))) % MOD;
if (k >= && (M-(j+k-)) >= && j >= )
f[i][j][k] = (f[i][j][k] + f[i-][j][k-] * (M-(j+k-)) * j) % MOD;
if (k >= )
f[i][j][k] = (f[i][j][k] + f[i-][j+][k-] * C(j+)) % MOD;
//不放
f[i][j][k] = (f[i][j][k] + f[i-][j][k]) % MOD;
}
}
}
ll ans = ;
for (int j = ; j <= M; j++)
for (int k = ; k+j <= M; k++)
ans = (ans + f[N][j][k]) % MOD;
cout << ans << endl;
return ;
}

洛谷P2051 中国象棋(dp)的更多相关文章

  1. 洛谷P2051 中国象棋

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

  2. 洛谷 - P2051 - 中国象棋 - 简单dp

    https://www.luogu.org/problemnew/show/P2051 一点都不简单的简单dp. 还是从旧行转移到新行,而不是考虑新行从哪些旧行转移吧. #include<bit ...

  3. 洛谷P2051 中国象棋【dp】

    题目:https://www.luogu.org/problemnew/show/P2051 题意:n*m的格子里放炮,使他们不能互相攻击. 如果两个炮在同一行同一列并且中间还有一个棋子的话就可以攻击 ...

  4. 洛谷 [P2051] 中国象棋

    DP orz__stdcall 首先要想出来,每行最多只能放两个棋子,这是显然的 于是决策就是一行一行地处理 30分的做法就是裸的枚举,暴搜,枚举这一行放哪里,放几个 然后想到了压位dp,按3进制表示 ...

  5. 洛谷 P2051 中国象棋 题解

    题面 状态可能不太好想,设f[i][j][k]表示前i行其中有j行是放一个炮,有k行是放两个炮的合法方案数: 那么: f[i+1][j][k]+=f[i][j][k]     在这一行不放任何棋子: ...

  6. P2051 中国象棋

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

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

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

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

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

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

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

随机推荐

  1. Mysql 用户ip访问根据省份查询

    表名:shop_interview_customer 表结构:customerId空为游客模式 interviedId customerId interviewIP iPdetail 1 1001 1 ...

  2. matlab画图变粗脚本

    http://blog.sina.com.cn/s/blog_708637950100uag0.html figure_FontSize=18;set(get(gca,'XLabel'),'FontS ...

  3. OOP⑵

    1.问题? 怎么创建对象? 类名 对象名=new 类名(); 在java中只要是看到了()! 这就是方法! 2.构造方法: 创建某个对象的方法! Student stu=new Student(); ...

  4. 1014 2018 使用FLAG counter

    AmazingCounters.com 不能用了,服务器访问不了了,之前的博客浏览量也看不到了,1014号换了个新的--FLAG counter,就是博客右边那个.

  5. sqlalchemy 简介

    #! /usr/bin/env python3 # -*- coding:utf-8 -*- #use SQLAlchemy #ORM:Object-Relational Mapping ,把关系数据 ...

  6. 如何在Ubuntu中安装中文输入法

    在使用ubuntu系统时,有的时候总觉得英文输入法不方便操作,总希望能有中文输入法可以辅助操作,那怎样才能在ubuntu中安装中文输入法呢?下面有一种简单的方法可以安装中文输入法. 如何在ubuntu ...

  7. SimpleDateFormat的安全问题解决方法

    问题: SimpleDateFormat 是线程不安全的类,一般不要定义为static变量,如果定义为static,必须加锁,或者使用DateUtils工具类. 而且SimpleDateFormat ...

  8. Codeforces Round #485 (Div. 2) C题求三元组(思维)

    C. Three displays time limit per test 1 second memory limit per test 256 megabytes input standard in ...

  9. SpringMVC学习三

    实现有点用处的增删改查,并利用了AJAX(javascript)动态修改,还有json的返回读取,以及文件上传和下载. 配置基础Employee类以及Dao类 package com.springmv ...

  10. leetcode第四题:两个有序数组的中位数

    给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和 nums2  ...