BZOJ 1801 中国象棋

终于大概会推dp方程了。。。然而怎么定义状态是个麻烦的事情。

很多时候感觉想不到。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mod 9999973
using namespace std;
long long n,m,dp[105][105][105];
long long calc(long long x) {return (x*(x-1)/2)%mod;}
int main()
{
    scanf("%lld%lld",&n,&m);
    dp[0][0][0]=1;
    for (long long i=1;i<=n;i++)
        for (long long j=0;j<=m;j++)
            for (long long k=0;k<=m-j;k++)
            {
                dp[i][j][k]+=dp[i-1][j][k];dp[i][j][k]%=mod;
                if (j) dp[i][j][k]+=dp[i-1][j-1][k]*(m-j-k+1)%mod;dp[i][j][k]%=mod;
                if ((k) && (j<=m-1)) dp[i][j][k]+=dp[i-1][j+1][k-1]*(j+1)%mod;dp[i][j][k]%=mod;
                if (j>=2) dp[i][j][k]+=dp[i-1][j-2][k]*calc(m-j-k+2)%mod;dp[i][j][k]%=mod;
                if (k) dp[i][j][k]+=dp[i-1][j][k-1]*(j*(m-j-k+1)%mod)%mod;dp[i][j][k]%=mod;
                if ((k>=2) && (j<=m-2)) dp[i][j][k]+=dp[i-1][j+2][k-2]*calc(j+2)%mod;
            }
    long long ans=0;
    for (int i=0;i<=m;i++)
        for (int j=0;j<=m-i;j++)
            ans=(ans+dp[n][i][j])%mod;
    printf("%lld\n",ans);
    return 0;
}
时间: 2024-12-15 10:09:38

BZOJ 1801 中国象棋的相关文章

BZOJ 1801 中国象棋(DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1801 题意:在n*m的棋盘上放若干炮使得不互相攻击.有多少种放法?可以放0个.1个....只要不互相攻击就行.. 思路:f[i][j][k]前i行j列有1个炮.k列有两个炮. int n,m; i64 f[N][N][N]; void up(i64 &x,i64 y) { x+=y; x%=mod; } i64 C(int x) { return x*(x-1)/2; } int ma

BZOJ 1801中国象棋 DP

将题目化简为设计01矩阵 每一行每一列至多2个1.求有几种方案. 设f[i][j][k]代表到第i行有j列放了1个象棋k列放了0个象棋有两个象棋的列不用考虑因为不能再放了. 递推方程如下: f[i][j][k]=f[i-1][j][k] 第i行不放. f[i][j][k]+=f[i-1][j-1][k+1]*(k+1) 在i-1行中任选一列(该列的棋子数=0)后面放一颗.有 k+1种放法. f[i][j][k]+=f[i-1][j+1][k]*(j+1)     选一列(该列棋子数=1) f[i

BZOJ 1801: [Ahoi2009]chess 中国象棋( dp )

dp(i, j, k)表示考虑了前i行, 放了0个炮的有j列, 放了1个炮的有k列. 时间复杂度O(NM^2) -------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const in

p2051 [AHOI2009]中国象棋. (bzoj 1801)

题目描述 这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法.大家肯定很清楚,在中国象棋中炮的行走方式是:一个炮攻击到另一个炮,当且仅当它们在同一行或同一列中,且它们之间恰好 有一个棋子.你也来和小可可一起锻炼一下思维吧! 40pts 考试遇到了这个题,玄学打表得了\(40pts\) 玄学打表吼啊 xjb分析 正解竟然是个\(DP\)? 还有人说是状压\(DP\)?哪里来的状压啊! 前置知识 考虑到我

动态规划 BZOJ1801 [Ahoi2009]chess 中国象棋

1801: [Ahoi2009]chess 中国象棋 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1861  Solved: 1068[Submit][Status][Discuss] Description 在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮. 请问有多少种放置方法,中国像棋中炮的行走方式大家应该很清楚吧. Input 一行包含两个整数N,M,中间用空格分开. Output 输出所有的方案数,由于值比较

BZOJ1801:[AHOI2009]中国象棋——题解

http://www.lydsy.com/JudgeOnline/problem.php?id=1801 https://www.luogu.org/problemnew/show/P2051 这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法.大家肯定很清楚,在中国象棋中炮的行走方式是:一个炮攻击到另一个炮,当且仅当它们在同一行或同一列中,且它们之间恰好 有一个棋子.你也来和小可可一起锻炼一下思维吧

[AHOI2009]中国象棋

题目描述 这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法.大家肯定很清楚,在中国象棋中炮的行走方式是:一个炮攻击到另一个炮,当且仅当它们在同一行或同一列中,且它们之间恰好 有一个棋子.你也来和小可可一起锻炼一下思维吧! 输入输出格式 输入格式: 一行包含两个整数N,M,之间由一个空格隔开. 输出格式: 总共的方案数,由于该值可能很大,只需给出方案数模9999973的结果. 输入输出样例 输入样例#

团队-编程项目 中国象棋-需求分析

需求分析: 1.棋盘和棋子的绘制 2.按照象棋规则对棋子进行布局   3.鼠标响应 : 在对弈中,棋子是必须可以移动的,不然游戏无法进行.因此,鼠标左键点击是必不可少的一部分. 4.棋子的功能分析:  中国象棋中各色的象棋棋子的功能使象棋具有了真正的趣味性,中国象棋的棋子的类型大致分为:帅(将).士.象.马.车.炮.兵(卒)等几个类型.  帅(将):红方中的帅和黑方中的将的功能相同,都是只能在九宫格中进行横向和竖向的移动,每次移动一格,并且不能移动超出九宫格,帅和将不能见面.  士:士在整片棋盘

JavaScript中国象棋程序(0) - 前言

"JavaScript中国象棋程序" 这一系列教程将带你从头使用JavaScript编写一个中国象棋程序.希望通过这个系列,我们对博弈程序的算法有一定的了解.同时,我们也将构建出一个不错的中国象棋程序. JavaScript中国象棋程序系列共有9个部分: 0.JavaScript中国象棋程序(0)- 前言 1.JavaScript中国象棋程序(1)- 界面设计 2.JavaScript中国象棋程序(2)- 校验棋子走法 3.JavaScript中国象棋程序(3)- 电脑自动走棋 4.J