bzoj 1037[ZJOI2008]生日聚会Party - dp
1037: [ZJOI2008]生日聚会Party
Time Limit: 10 Sec Memory Limit: 162 MBDescription
今天是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。
开始yy了一个三维的dp,于是就gg了,然后想到了4维的方法
我们用 f[i][j][k1][k2] 表示当前放到第i个位置一共放了j个男生并且序列结尾最大的男生减女生的数量差有 k1个, 女生减男生的差有k2个
这样能写出转移方程
放男生 :
f[i][j][k1][k2] += f[i - 1][j - 1][k1 - 1][k2 + 1]
放女生 :
f[i][j][k1][k2] += f[i - 1][j][k1 + 1][k2 - 1]
注意当 k1 = 0 时, 放女生不会改变k1 所以:
f[i][j][0][k2] += f[i - 1][j][0][k2 - 1]
k2 = 0时同理
f[i][j][k1][0] += f[i - 1][j - 1][k1 - 1][0]
开始空间算错了还以为要滚动 2333
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #define LL long long 6 7 using namespace std; 8 9 LL mod = 12345678; 10 int n, m, K; 11 int now = 1; 12 LL ans = 0; 13 LL f[2][160][22][22]; 14 inline LL read() 15 { 16 LL x = 0, w = 1; char ch = 0; 17 while(ch < '0' || ch > '9') { 18 if(ch == '-') { 19 w = -1; 20 } 21 ch = getchar(); 22 } 23 while(ch >= '0' && ch <= '9') { 24 x = x * 10 + ch - '0'; 25 ch = getchar(); 26 } 27 return x * w; 28 } 29 30 int main() 31 { 32 n = read(), m = read(), K = read(); 33 f[0][0][0][0] = 1; 34 for(int i = 1; i <= n + m; i++) { 35 memset(f[now], 0, sizeof f[now]); 36 for(int j = 0; j <= n; j++) { 37 for(int k1 = 0; k1 <= K; k1++) { 38 for(int k2 = 0; k2 <= K; k2++) { 39 /*if(j > 0) { 40 f[i][j][k] += f[i - 1][j - 1][k - 1] % mod; 41 } 42 f[i][j][k] = (f[i][j][k] + f[i - 1][j][k + 1]) % mod;*/ 43 if(k2 != 0) { 44 f[now][j][k1][k2] = (f[now][j][k1][k2] + f[now ^ 1][j][k1 + 1][k2 - 1]) % mod; 45 if(k1 == 0) { 46 f[now][j][0][k2] = (f[now][j][0][k2] + f[now ^ 1][j][0][k2 - 1]) % mod; 47 } 48 } 49 if(k1 != 0 && j != 0) { 50 f[now][j][k1][k2] = (f[now][j][k1][k2] + f[now ^ 1][j - 1][k1 - 1][k2 + 1]) % mod; 51 if(k2 == 0) { 52 f[now][j][k1][0] = (f[now][j][k1][0] + f[now ^ 1][j - 1][k1 - 1][0]) % mod; 53 } 54 } 55 } 56 } 57 } 58 now = now ^ 1; 59 } 60 /* for(int i = 1; i <= n + m; i++) { 61 cout<<i<<endl; 62 for(int j = 0; j <= n; j++) { 63 for(int k = 30 - K; k <= 30 + K; k++) { 64 cout<<f[i][j][k]<<" "; 65 } 66 cout<<endl; 67 } 68 cout<<endl<<endl; 69 }*/ 70 /*for(int i = 1; i <= n + m; i++) { 71 for(int j = 0; j <= n; j++) { 72 for(int k1 = 0; k1 <= K; k1++) { 73 for(int k2 = 0; k2 <= K; k2++) { 74 cout<<f[i][j][k1][k2]<<" "; 75 } 76 cout<<endl; 77 } 78 cout<<endl; 79 } 80 cout<<endl<<endl; 81 }*/ 82 for(int k1 = 0; k1 <= K; k1++) { 83 for(int k2 = 0; k2 <= K; k2++) { 84 ans = (ans + f[now ^ 1][n][k1][k2]) % mod; 85 } 86 } 87 printf("%lld\n", ans); 88 return 0; 89 } 90 91 /* 92 93 1 2 1 94 */