zoukankan      html  css  js  c++  java
  • P2051 [AHOI2009]中国象棋 DP

    题目描述

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

    输入输出格式

    输入格式:

    一行包含两个整数N,M,之间由一个空格隔开。

    输出格式:

    总共的方案数,由于该值可能很大,只需给出方案数模9999973的结果。

    输入输出样例

    输入样例#1: 复制
    1 3
    输出样例#1: 复制
    7

    说明

    样例说明

    除了3个格子里都塞满了炮以外,其它方案都是可行的,所以一共有2*2*2-1=7种方案。

    数据范围

    100%的数据中N和M均不超过100

    50%的数据中N和M至少有一个数不超过8

    30%的数据中N和M均不超过6

    思路:f[i][j][k]代表填满i行时有j列有一个棋子,k列有2个棋子的方案数,枚举当前行填棋子的个数及位置可以很快得出转移方程。

    代码:

     1 #include"bits/stdc++.h"
     2 #define db double
     3 #define ll long long
     4 #define vec vector<ll>
     5 #define Mt  vector<vec>
     6 #define ci(x) scanf("%d",&x)
     7 #define cd(x) scanf("%lf",&x)
     8 #define cl(x) scanf("%lld",&x)
     9 #define pi(x) printf("%d
    ",x)
    10 #define pd(x) printf("%f
    ",x)
    11 #define pl(x) printf("%lld
    ",x)
    12 #define rep(i, n) for(int i=0;i<n;i++)
    13 using namespace std;
    14 const int N = 1e6 + 5;
    15 const int mod = 1e9 + 7;
    16 const int MOD = 9999973;
    17 const int inf = 0x3f3f3f3f;
    18 const db PI = acos(-1.0);
    19 const db eps = 1e-10;
    20 ll f[105][105][105];
    21 int n,m;
    22 ll C(int x)
    23 {
    24     return 1ll*x*(x-1)/2%MOD;
    25 }
    26 int main()
    27 {
    28     ci(n),ci(m);
    29     memset(f,0, sizeof(f));
    30     f[0][0][0]=1;
    31     for(int i=0;i<n;i++){
    32         for(int j=0;j<=m;j++){
    33             for(int k=0;k+j<=m;k++){
    34                 if(f[i][j][k]!=0){
    35                     f[i+1][j][k]=(f[i+1][j][k]+f[i][j][k])%MOD;
    36                     if(m-k-j>=1) f[i+1][j+1][k]=(f[i+1][j+1][k]+(m-k-j)*f[i][j][k]%MOD)%MOD;
    37                     if(j>=1) f[i+1][j-1][k+1]=(f[i+1][j-1][k+1]+j*f[i][j][k]%MOD)%MOD;
    38                     if(m-k-j>=2) f[i+1][j+2][k]=(f[i+1][j+2][k]+C(m-k-j)*f[i][j][k]%MOD)%MOD;
    39                     if(j>=2) f[i+1][j-2][k+2]=(f[i+1][j-2][k+2]+C(j)*f[i][j][k]%MOD)%MOD;
    40                     if(j>=1&&m-k-j>=1) f[i+1][j][k+1]=(f[i+1][j][k+1]+j*(m-k-j)*f[i][j][k]%MOD)%MOD;
    41                 }
    42             }
    43         }
    44     }
    45     ll ans=0;
    46     for(int j=0;j<=m;j++){
    47         for(int k=0;k+j<=m;k++){
    48             ans=(ans+f[n][j][k])%MOD;
    49         }
    50     }
    51     pl(ans);
    52 }
  • 相关阅读:
    Python单例模式中的4种方式
    Python list,tuple,dict,set高级变量常用方法
    python如何获取多个excel单元格的值
    两种方法实现python操作日志的封装
    numpy中函数shape的用法
    python中timer定时器常用的两种实现方法
    详解Python中argpasrse模块的基本使用
    在python中列表删除和多重循环退出
    Python的驻留机制(仅对数字,字母,下划线有效)
    python实现tail -f 功能
  • 原文地址:https://www.cnblogs.com/mj-liylho/p/9428103.html
Copyright © 2011-2022 走看看