zoukankan      html  css  js  c++  java
  • bzoj 4806: 炮

    4806: 炮

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 663  Solved: 320
    [Submit][Status][Discuss]

    Description

    众所周知,双炮叠叠将是中国象棋中很厉害的一招必杀技。炮吃子时必须隔一个棋子跳吃,即俗称"炮打隔子"。 
    炮跟炮显然不能在一起打起来,于是rly一天借来了许多许多的炮在棋盘上摆了起来……他想知道,在N×M的矩形
    方格中摆若干炮(可以不摆)使其互不吃到的情况下方案数有几种。
    棋子都是相同的。

     

    Input

    一行,两个正整数N和M。
    N<=100,M<=100

     

    Output

    一行,输出方案数mod 999983。

     

    Sample Input

    1 3

    Sample Output

    7

    HINT

     

    Source

    By FancyCoder

    思路:f[i][j][k]表示截止到第i行为止,在所有的列中有一个炮的有j列,有2个炮的有k列。

    举一个例子:

    比如,这个图假设是截止到第3行为止,就可以表示成f[3][6][1]。

    然后,我们就可以推想出以下6种状态:

    1:在下一行什么也不放: f[i+1][j][k]=f[i+1][j][k]+f[i][j][k];

    2:在下一行中找一个0个炮的列去放一个炮:  f[i+1][j+1][k]=f[i+1][j+1][k]+f[i][j][k]*(m-j-k);

    3:在下一行中找一个1个炮的列去放一个炮:  f[i+1][j-1][k+1]=f[i+1][j-1][k+1]+f[i][j][k]*j;

    4:在下一行中找两个0个炮的列去分别放一个炮:  f[i+1][j+2][k]=f[i+1][j+2][k]+f[i][j][k]*(m-j-k)*(m-j-k-1)/2;

    (这里运用了组合数公式,因为有m-j-k个0个炮的列,任选两个进行组合,一共有C2m-j-k种放法,化简开来就是有(m-j-k)*(m-j-k-1)/2种)

    5:在下一行中找一个0个炮的列和一个1个炮的列分别去放一个炮:  f[i+1][j][k+1]=f[i+1][j][k+1]+f[i][j][k]*(m-j-k)*j;

    6:在下一行中找两个1个炮的列去分别放一个炮:  f[i+1][j-2][k+2]=f[i+1][j-2][k+2]+f[i][j][k]*j*(j-1)/2;

    最后的ans是所有的f[n]加起来:  ans=ans+f[n][j][k];

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define mod 999983
    #define MAXN 110
    using namespace std; 
    int n,m,i,j,k; 
    long long f[MAXN][MAXN][MAXN];
    int main(){
        //freopen("B.in","r",stdin);
        //freopen("B.out","w",stdout);
        scanf("%d%d",&n,&m); 
        f[0][0][0]=1; 
        for(int i=0;i<=n-1;i++) 
            for(int j=0;j<=m;j++)
                for(int k=0;k<=m-j;k++)
                    if(f[i][j][k]){ 
                        f[i+1][j][k]=(f[i+1][j][k]+f[i][j][k])%mod; 
                        f[i+1][j+1][k]=(f[i+1][j+1][k]+f[i][j][k]*(m-j-k))%mod; 
                        if(j>=1)    f[i+1][j-1][k+1]=(f[i+1][j-1][k+1]+f[i][j][k]*j)%mod;   
                        if(m-j-k>=2)    f[i+1][j+2][k]=(f[i+1][j+2][k]+f[i][j][k]*((m-j-k)*(m-j-k-1)/2))%mod; 
                        if(j>=1&&m-j-k>=1)    f[i+1][j][k+1]=(f[i+1][j][k+1]+f[i][j][k]*(j*(m-j-k)))%mod; 
                        if(j>=2)    f[i+1][j-2][k+2]=(f[i+1][j-2][k+2]+f[i][j][k]*(j*(j-1)/2))%mod; 
                    } 
        long long ans=0; 
        for(int j=0;j<=m;j++)
            for(int k=0;k<=m-j;k++)
                ans=(ans+f[n][j][k])%mod; 
        cout<<ans; 
    }
    细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
  • 相关阅读:
    在QT中应用中文
    DDA画直线
    裁剪算法
    VC6与office2007冲突的解决方法
    肾形图案
    OPENGL函数说明
    基数排序
    Qt信号和槽机制
    分形曼德尔波集合图形
    分形朱利亚集合图形1
  • 原文地址:https://www.cnblogs.com/cangT-Tlan/p/7567603.html
Copyright © 2011-2022 走看看