zoukankan      html  css  js  c++  java
  • 【BZOJ1037】[ZJOI2008]生日聚会(动态规划)

    【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
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    shell命令finger
    join命令
    日志记录
    shell命令xargs
    linux read 简介
    P1601 A+B Problem(高精)
    P2670 [NOIP2015 普及组] 扫雷游戏
    P1042 [NOIP2003 普及组] 乒乓球
    P1328 [NOIP2014 提高组] 生活大爆炸版石头剪刀布
    P5744 【深基7.习9】培训
  • 原文地址:https://www.cnblogs.com/cjyyb/p/9723001.html
Copyright © 2011-2022 走看看