1037: [ZJOI2008]生日聚会Party - BZOJ
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
对于30%的数据,n , m ≤ 20;对于100%的数据, n , m ≤ 150,k ≤ 20。
裸dp,f[a,b,c,d]表示有a个女的,b个男的,以最后一个人为右端点的女的最多比男的多c个,男的最多比女的多d个
(你要问我为什么这样表示,为什么第一维不是长度,我只能说Wikioi的云IDE内存不够大,况且我习惯用广度优先搜索,这样表示没有浪费空间,如果第一维是长度,那a<b的那一部分就用不到了,很浪费)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 const 2 h=12345678; 3 maxq=150*20*20*10; 4 type 5 point=record 6 a,b,c,d:longint; 7 end; 8 var 9 f:array[0..150,0..150,0..20,0..20]of longint; 10 q:array[0..maxq]of point; 11 n,m,k,head,tail,ans:longint; 12 13 function max(x,y:longint):longint; 14 begin 15 if x>y then exit(x); 16 exit(y); 17 end; 18 19 procedure main; 20 begin 21 read(n,m,k); 22 head:=1; 23 tail:=2; 24 fillchar(f,sizeof(f),1); 25 f[0,0,0,0]:=1; 26 while head<>tail do 27 begin 28 with q[head] do 29 if (a=n) and (b=m) then ans:=(ans+f[a,b,c,d])mod h 30 else 31 begin 32 if (a<n) and (c<k) then 33 begin 34 if f[a+1,b,c+1,max(0,d-1)]>h then 35 begin 36 q[tail].a:=a+1; 37 q[tail].b:=b; 38 q[tail].c:=c+1; 39 q[tail].d:=max(0,d-1); 40 f[a+1,b,c+1,max(0,d-1)]:=0; 41 tail:=tail mod maxq+1; 42 end; 43 f[a+1,b,c+1,max(0,d-1)]:=(f[a+1,b,c+1,max(0,d-1)]+f[a,b,c,d])mod h; 44 end; 45 if (b<m) and (d<k) then 46 begin 47 if f[a,b+1,max(0,c-1),d+1]>h then 48 begin 49 q[tail].a:=a; 50 q[tail].b:=b+1; 51 q[tail].c:=max(0,c-1); 52 q[tail].d:=d+1; 53 f[a,b+1,max(0,c-1),d+1]:=0; 54 tail:=tail mod maxq+1; 55 end; 56 f[a,b+1,max(0,c-1),d+1]:=(f[a,b+1,max(0,c-1),d+1]+f[a,b,c,d])mod h; 57 end; 58 end; 59 head:=head mod maxq+1; 60 end; 61 write(ans); 62 end; 63 64 begin 65 main; 66 end.