bzoj 1151: [CTSC2007]动物园zoo

思路:因为每个人最多只能看到五个动物,我们考虑将其状压,f[ i ][ s ] 表示到了第 i 个位置, i, i + 1, i + 2, i + 3, i + 4这四个动物的状态为s,

此时的最大值。 因为它是一个环,所以我们考虑枚举前4位,这样就能dp啦,dp[i][s] = max(dp[i - 1][(15 & s) << 1], dp[i - 1][(15 & s) << 1 | 1]) + val[i][s];

val[ i ]][ s ] 是预处理出来,在i这个位置的人在s这个状态的贡献。

 1 #include<bits/stdc++.h>
 2 #define LL long long
 3 #define fi first
 4 #define se second
 5 #define mk make_pair
 6 #define pii pair<int,int>
 7 #define piii pair<int, pair<int,int>>
 8 
 9 using namespace std;
10 
11 const int N=10000+7;
12 const int M=1e4+7;
13 const int inf=0x3f3f3f3f;
14 const LL INF=0x3f3f3f3f3f3f3f3f;
15 const int mod=1e9 + 7;
16 
17 int n, m, val[N][32], dp[N][32];
18 int main() {
19     scanf("%d%d", &n, &m);
20     for(int k = 1; k <= m; k++) {
21         int pos; scanf("%d", &pos);
22         int cnt1, cnt2, s1 = 0, s2 = 0;
23         scanf("%d%d", &cnt1, &cnt2);
24         for(int i = 1; i <= cnt1; i++) {
25             int x; scanf("%d", &x);
26             s1 |= 1 << ((x - pos + n) % n);
27         }
28         for(int i = 1; i <= cnt2; i++) {
29             int x; scanf("%d", &x);
30             s2 |= 1 << ((x - pos + n) % n); 
31         }
32 
33         for(int j = 0; j < 32; j++) {
34             if(j & s1 || (31 ^ j) & s2) {
35                 val[pos][j]++;
36             }
37         }
38     }
39 
40     int ans = 0;
41     for(int s1 = 0; s1 < 16; s1++) {
42         for(int i = 0; i < 32; i++) dp[0][i] = -inf;
43         dp[0][s1 << 1] = 0;
44         for(int i = 1; i <= n; i++) {
45             for(int s = 0; s < 32; s++) {
46                 dp[i][s] = max(dp[i - 1][(15 & s) << 1], dp[i - 1][(15 & s) << 1 | 1]) + val[i][s];
47             }
48         }
49         ans = max(ans, max(dp[n][s1 << 1], dp[n][s1 << 1 | 1]));
50     }
51 
52     printf("%d
", ans);
53     return 0;
54 }
55 /*
56 */
原文地址:https://www.cnblogs.com/CJLHY/p/9055675.html