Bzoj 4806 炮 (dp)

题目描述

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

输入输出格式

输入格式:
一行,两个正整数N和M。
N<=100,M<=100
输出格式:

一行,输出方案数mod 999983。

输入输出样例

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

分析 :

显然一行一列只能放2个或以下棋子, 否则会相互攻击;
明显的DP;
定义f[i][j][k] , 表示前i行, 有j列是放了1个, k列放了两个;

转移方程 :

f[i][j][k] += f[i-1][j][k] 什么都没放;
f[i][j][k] += f[i-1][j-1][k] * (m - (j - 1) - k) 在没放棋子的一列放了一个;
f[i][j][k] += f[i-1][j+1][k-1] * (j + 1) 在有一个棋子的一列放了一个, 变成了两个;
f[i][j][k] += f[i-1][j-2][k] * C(m - (j - 2) - k, 2) 在没放棋子的两列分别放两个棋子;
f[i][j][k] += f[i-1][j][k-1] * j * (m - (j - 1) - k) 直接在没放棋子的一列放上两个棋子;
f[i][j][k] += f[i-1][j+2][k-2] * C(j + 2, 2) 在放了一个棋子的两列风别放上一个;

记得取模;

代码奉上
// By zZhBr
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int p = 999983;
#define int long long

int n, m;

int f[105][105][105];

int ans;

signed main()
{
    cin >> n >> m;
    
    f[0][0][0] = 1;
    
    for(register int i = 1 ; i <= n ; i ++)
    {
        for(register int j = 0 ; j <= m ; j ++)
        {
            for(register int k = 0 ; k <= m - j ; k ++)
            {
                
                f[i][j][k] = (f[i][j][k] + f[i-1][j][k]) % p;
                
                if(j - 1 >= 0)
                    f[i][j][k] = (f[i][j][k] + f[i-1][j-1][k] * (m - (j - 1) - k)) % p;
                
                if(k - 1 >= 0)
                    f[i][j][k] = (f[i][j][k] + f[i-1][j+1][k-1] * (j + 1))% p;
                
                if(j - 2 >= 0)    
                {    
                    int t = m - (j - 2) - k;
                    f[i][j][k] = (f[i][j][k] + f[i-1][j-2][k] * (t * (t - 1)) / 2) % p;
                }
                
                if(k - 2 >= 0)
                    f[i][j][k] = (f[i][j][k] + f[i-1][j+2][k-2] * (j + 1) * (j + 2) / 2) % p;
                
                if(k - 1 >= 0)
                    f[i][j][k] = (f[i][j][k] + f[i-1][j][k-1] * j * (m - (j - 1) - k)) % p;
                
                if(i == n) ans = (ans + f[i][j][k]) % p;
                
                //printf("n == %lld,  f[i][j][k] == %lld\n", i, f[i][j][k]);
            }
        }
    }
    
    cout << ans << endl;
    
    return 0;
}
zZhBr

 




提交地址 https://www.lydsy.com/JudgeOnline/problem.php?id=4806 ;





posted @ 2018-04-26 08:40  zZhBr  阅读(175)  评论(0编辑  收藏  举报