1037: [ZJOI2008]生日聚会Party
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1583 Solved: 936
[Submit][Status][Discuss]
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
对于100%的数据, n , m ≤ 150,k ≤ 20。
Source
题解:一眼DP,不过状态好像挺难想的。。。
设dp[i][j][k1][k2]表示前i个人中,有j个男孩,男孩最多比女孩多k1个,女孩最多比男孩多k2个的最大方案数。。。
然后分男孩女孩转移
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<queue> 6 #include<cstring> 7 #define PAU putchar(' ') 8 #define ENT putchar(' ') 9 using namespace std; 10 const int maxn=20+5,maxm=150+10; 11 int n,m,k,dp[2][maxm][maxn][maxn]; 12 int mod=12345678; 13 inline int read(){ 14 int x=0,sig=1;char ch=getchar(); 15 for(;!isdigit(ch);ch=getchar())if(ch=='-')sig=0; 16 for(;isdigit(ch);ch=getchar())x=10*x+ch-'0'; 17 return sig?x:-x; 18 } 19 inline void write(int x){ 20 if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x; 21 int len=0,buf[15];while(x)buf[len++]=x%10,x/=10; 22 for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return; 23 } 24 void init(){ 25 n=read();m=read();k=read(); 26 int tp=0;dp[0][0][0][0]=1; 27 for(int i=0;i<n+m;i++){ 28 tp^=1; 29 memset(dp[tp],0,sizeof(dp[tp])); 30 for(int j=0;j<=min(i,n);j++) 31 for(int k1=0;k1<=min(j,k);k1++) 32 for(int k2=0;k2<=min(i-j,k);k2++){ 33 if(k1<k&&j<n)(dp[tp][j+1][k1+1][max(k2-1,0)]%=mod)+=(dp[tp^1][j][k1][k2]%=mod); 34 if(k2<k&&i-j<m)(dp[tp][j][max(k1-1,0)][k2+1]%=mod)+=(dp[tp^1][j][k1][k2]%=mod); 35 } 36 } 37 int ans=0; 38 for(int k1=0;k1<=k;k1++) 39 for(int k2=0;k2<=k;k2++) 40 (ans+=(dp[tp][n][k1][k2]%=mod))%=mod; 41 write(ans); 42 return; 43 } 44 void work(){ 45 return; 46 } 47 void print(){ 48 return; 49 } 50 int main(){init();work();print();return 0;}