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

    题目描述

    这次小可可想解决的难题和中国象棋有关,在一个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



    然后我想到了压位dp,按3进制表示当前棋盘的状态,即某一列没有棋子,或者有一个,两个棋子,能过50分

    接着可以发现,棋子的顺序是无所谓的,并不需要准确知道当前棋盘的状态

    于是有了100分做法:dp[i][j][k]表示放了前i行,有j列是有1个棋子,有k列有两个棋子、



     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cmath>
     4 #include<cctype>
     5 #include<cstring>
     6 #define mod 9999973
     7 #define int long long
     8 #define R register
     9 using namespace std;
    10 inline  void in(int &x)
    11 {
    12     int f=1;x=0;char s=getchar();
    13     while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
    14     while(isdigit(s)){x=x*10+s-'0';s=getchar();}
    15     x*=f;
    16 }
    17 int n,m,ans;
    18 int f[108][108][108];
    19 inline int C(int x)
    20 {
    21     return ((x*(x-1))/2)%mod;
    22 }
    23 signed main()
    24 {
    25     in(n),in(m);
    26     f[0][0][0]=1;
    27     for(R int i=1;i<=n;i++)
    28     {
    29         for(R int j=0;j<=m;j++)
    30         {
    31             for(R int k=0;k<=m-j;k++)
    32             {
    33                 f[i][j][k]=f[i-1][j][k];
    34                 if(k>=1)(f[i][j][k]+=f[i-1][j+1][k-1]*(j+1));
    35                 if(j>=1)(f[i][j][k]+=f[i-1][j-1][k]*(m-j-k+1));
    36                 if(k>=2)(f[i][j][k]+=f[i-1][j+2][k-2]*(((j+2)*(j+1))/2));
    37                 if(k>=1)(f[i][j][k]+=f[i-1][j][k-1]*j*(m-j-k+1));
    38                 if(j>=2)(f[i][j][k]+=f[i-1][j-2][k]*C(m-j-k+2));
    39                 f[i][j][k]%=mod;
    40             }
    41         }
    42     }
    43     for(R int i=0;i<=m;i++)
    44         for(R int j=0;j<=m;j++)
    45             (ans+=f[n][i][j])%=mod;
    46     printf("%lld",(ans+mod)%mod);
    47 }
  • 相关阅读:
    Leetcode Reverse Words in a String
    topcoder SRM 619 DIV2 GoodCompanyDivTwo
    topcoder SRM 618 DIV2 MovingRooksDiv2
    topcoder SRM 618 DIV2 WritingWords
    topcoder SRM 618 DIV2 LongWordsDiv2
    Zepto Code Rush 2014 A. Feed with Candy
    Zepto Code Rush 2014 B
    Codeforces Round #245 (Div. 2) B
    Codeforces Round #245 (Div. 2) A
    Codeforces Round #247 (Div. 2) B
  • 原文地址:https://www.cnblogs.com/zhangbuang/p/10356178.html
Copyright © 2011-2022 走看看