[ZJOI]2008 生日聚会

 


 

显然DP。

将题目转化下: 求由n个0、m个1组成,且满足任意子串0的数量和1的数量差绝对值不超过k的01串数量。n, m≤150,k≤20。

直接做没什么思路,,那我们尽量利用题目的时间和空间限制,以达到清晰、方便的方程转移。

 


 

 

由于题目n、m很小,可以考虑O(nm)带k的几次方的算法。

设f[a][b][l][h]表示当前序列中放了a个1,b个0,所有后缀中,男生减女生的差最大为l,女生减男生的差最大为h的方案数。

那么状态转移显然->  f[a][b][l][h] 可以向 f[a+1][b][l+1][max(h-1),0] 或 f[a][b+1][max(l-1)][h+1] 转移;最后答案统计f[n][m][l][h](枚举l,h)。

 

Code:

#include<bits/stdc++.h>
using namespace std;

const int maxn = 180;
const int mod = 12345678;

int f[maxn][maxn][26][26];

int main(){
    int n,m,k;
    cin>>n>>m>>k;
    f[0][0][0][0] = 1;
    for(int a = 0;a<=n;++a)
    for(int b = 0;b<=m;++b)
    for(int l = 0;l<=k;++l)
    for(int h = 0;h<=k;++h)
    if(f[a][b][l][h]){
        int cnt = f[a][b][l][h];
        f[a+1][b][l+1][max(h-1,0)] += cnt;f[a+1][b][l+1][max(h-1,0)]%=mod;
        f[a][b+1][max(l-1,0)][h+1] += cnt;f[a][b+1][max(l-1,0)][h+1]%=mod;
    }
    int ans = 0;
    for(int i = 0;i<=k;++i)
        for(int j = 0;j<=k;++j)
        ans = (ans + f[n][m][i][j])%mod;
    cout<<ans<<endl;
}

 

 

 

 

猜你喜欢

转载自www.cnblogs.com/guoyangfan/p/11237290.html