[ZJOI2008]生日聚会

嘟嘟嘟

此题一看就是一个dp题。

首先我们设dp[i][j]表示前 i 个人中有 j 个男生(这和dp[i][j]表示 i 个男生 j 个女生等价),然而当我们转移到dp[i + 1][j + 1]或dp[i + 1][j]时,限制条件没有用上。所以要再加两维dp[i][j][x][y]表示前 i 个人中有 j 个男生,其中男生最多比女生多个,女生最多比男生多y个。

这样很容易得出转移方程

    dp[i + 1][j + 1][x + 1][y - 1] += dp[i][j][x][y],

    dp[i + 1][j][x - 1][y + 1] += dp[i][j][x][y]

但是当y或是x已经是0的时候,那还应该是0

    dp[i + 1][j + 1][x + 1][max(y - 1, 0)] += dp[i][j][x][y],

    dp[i + 1][j][max(x - 1, 0)][y + 1] += dp[i][j][x][y]

 还有一件事我也不太懂,就是为啥dp[i][j][x][y]要从右面转移,而不是有的状态转移到dp[i][j][x][y]……巨佬们求助啊

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<vector>
 8 #include<queue>
 9 #include<stack>
10 #include<cctype>
11 using namespace std;
12 #define enter puts("")
13 #define space putchar(' ')
14 #define Mem(a) memset(a, 0, sizeof(a))
15 typedef long long ll;
16 typedef double db;
17 const int INF = 0x3f3f3f3f;
18 const db eps = 1e-8;
19 const int maxn = 155;
20 const int mod = 12345678;
21 inline ll read()
22 {
23     ll ans = 0;
24     char ch = getchar(), last = ' ';
25     while(!isdigit(ch)) last = ch, ch = getchar();
26     while(isdigit(ch)) ans = (ans << 3) + (ans << 1) + ch - '0', ch = getchar();
27     if(last == '-') ans = -ans;
28     return ans;
29 }
30 inline void write(ll x)
31 { 
32     if(x < 0) putchar('-'), x = -x;
33     if(x >= 10) write(x / 10);
34     putchar(x % 10 + '0');
35 }
36 
37 int n, m ,k;
38 int dp[maxn << 1][maxn][21][21], ans = 0;
39 
40 int main()
41 {
42     n = read(); m = read(); k = read();
43     dp[0][0][0][0] = 1;
44     for(int i = 0; i < n + m; ++i)
45         for(int j = 0; j <= n; ++j)
46             for(int x = 0; x <= k; ++x)
47                 for(int y = 0; y <= k; ++y)
48                 {
49                     if(!dp[i][j][x][y]) continue;
50                     if(j + 1 <= n && x + 1 <= k) dp[i + 1][j + 1][x + 1][max(y - 1, 0)] += dp[i][j][x][y] %= mod;
51                     if(y + 1 <= k) dp[i + 1][j][max(x - 1, 0)][y + 1] += dp[i][j][x][y] %= mod;
52                 }
53     for(int i = 0; i <= k; ++i)    
54         for(int j = 0; j <= k; ++j)
55         ans = (ans + dp[n + m][n][i][j]) % mod;
56     write(ans);
57     return 0;
58 }
View Code
原文地址:https://www.cnblogs.com/mrclr/p/9536332.html