[ZJOI2008]生日聚会Party

Description

  今天是hidadz小朋友的生日,她邀请了许多朋友来参加她的生日party。 hidadz带着朋友们来到花园中,打算
坐成一排玩游戏。为了游戏不至于无聊,就座的方案应满足如下条件:对于任意连续的一段,男孩与女孩的数目之
差不超过k。很快,小朋友便找到了一种方案坐了下来开始游戏。hidadz的好朋友Susie发现,这样的就座方案其实
是很多的,所以大家很快就找到了一种,那么到底有多少种呢?热爱数学的hidadz和她的朋友们开始思考这个问题
…… 假设参加party的人中共有n个男孩与m个女孩,你是否能解答Susie和hidadz的疑问呢?由于这个数目可能很
多,他们只想知道这个数目除以12345678的余数。

Input

  仅包含一行共3个整数,分别为男孩数目n,女孩数目m,常数k。

Output

  应包含一行,为题中要求的答案。

Sample Input

1 2 1

Sample Output

1

HINT

n , m ≤ 150,k ≤ 20。

分析:

这是一道计数类DP,我们考虑如何记录状态。首先用两维记录男生和女生的人数,然后我们再用两维记录从最大后缀
男生与女生人数差值和女生与男生的差值。在某一状态考虑向后增加男生或女生,增加男生的时候,男女差增大,女
男差减少,反之亦然。需要注意的是,当最大后缀差值减为负数时,将其当做0转移。

代码:

#include<cstdio>
#include<cctype>
#define maxn 155
#define mod 12345678
#define rep(i,j,k) for(int i=j;i<=k;i++)
template <typename _Tp> inline _Tp in(_Tp&x){
    char c11=getchar(),ob=0;x=0;
    while(c11^'-'&&!isdigit(c11))c11=getchar();if(c11=='-')c11=getchar(),ob=1;
    while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;return x;
}

int f[maxn][maxn][25][25];

inline void add(int &x,const int &y){
	x=(x+y)%mod;
	if(x<0) x+=mod;
	return ;
}

int main(){
	int n,m,k;
	in(n);in(m);in(k);
	f[0][0][0][0]=1;
	rep(i,0,n) rep(j,0,m) rep(x,0,k) rep(y,0,k){
		if(x+1<=k) add(f[i+1][j][x+1][y-1<0?0:y-1],f[i][j][x][y]);
		if(y+1<=k) add(f[i][j+1][x-1<0?0:x-1][y+1],f[i][j][x][y]);
	}
	int ans=0;
	for(int i=0;i<=k;i++)
		for(int j=0;j<=k;j++)
			add(ans,f[n][m][i][j]);
	printf("%d",ans);
	return 0;
}
posted @ 2018-10-22 20:16  IEQEFCR  阅读(162)  评论(0编辑  收藏  举报