bzoj 1037[ZJOI2008]生日聚会Party - dp

1037: [ZJOI2008]生日聚会Party

Time Limit: 10 Sec  Memory Limit: 162 MB

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。

 

开始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 */
View Code

 

 

 

posted @ 2018-02-27 15:49  大财主  阅读(172)  评论(0编辑  收藏  举报