首页 > 其他 > 详细

【BZOJ1037】[ZJOI2008]生日聚会(动态规划)

时间:2018-09-29 12:37:01      阅读:158      评论:0      收藏:0      [点我收藏+]

【BZOJ1037】[ZJOI2008]生日聚会(动态规划)

题面

BZOJ
洛谷

题解

假设前面的都合法,但是在加完当前的最后一个人之后变得不合法了,那么意味着一定有着一个后缀不合法。把男生看成\(1\),女生看成\(-1\),也就是不存在一个后缀和大于\(K\)或者一个后缀和小于\(-K\)。而在最后面加进一个男生或者女生显然就是把所有后缀\(+1\)或者\(-1\)。那么设\(f[i][j][k][l]\)表示当前考虑到了第\(i\)个位置,放了\(j\)\(1\),最大的后缀和为\(j\),最小的后缀和为\(-l\)的方案数。转移的时候判断一下是否合法就好了。
时间复杂度\(O(n^2k^2)\)

#include<iostream>
#include<cstdio>
using namespace std;
#define MOD 12345678
void add(int &x,int y){x+=y;if(x>=MOD)x-=MOD;}
int f[305][155][22][22];
int n,m,K,ans;
int main()
{
    scanf("%d%d%d",&n,&m,&K);
    f[0][0][0][0]=1;
    for(int i=1;i<=n+m;++i)
        for(int j=0;j<=i&&j<=n;++j)
            for(int k=0;k<=K;++k)
                for(int l=0;l<=K;++l)
                {
                    if(!f[i-1][j][k][l])continue;
                    if(j<n&&k!=K)add(f[i][j+1][k+1][max(0,l-1)],f[i-1][j][k][l]);
                    if(i-j-1<m&&l!=K)add(f[i][j][max(0,k-1)][l+1],f[i-1][j][k][l]);
                }
    for(int k=0;k<=K;++k)
        for(int l=0;l<=K;++l)
            add(ans,f[n+m][n][k][l]);
    printf("%d\n",ans);
    return 0;
}

【BZOJ1037】[ZJOI2008]生日聚会(动态规划)

原文:https://www.cnblogs.com/cjyyb/p/9723001.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!