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;
    }
    
  • 相关阅读:
    【Opencv】直方图函数 calchist()
    【Lintcode】070.Binary Tree Level Order Traversal II
    【C++】*p++ = *p不同环境下操作不同
    【Python】String 字符串
    【Python】File IO
    栈和队列
    链表
    printf 的格式
    Linux的基本指令--
    机器人的运动范围
  • 原文地址:https://www.cnblogs.com/cjyyb/p/9723001.html
Copyright © 2011-2022 走看看