【APIO2007】动物园

Description

Solution

每个人能看到的动物只有5个,所以我们可以将这个进行状压,定义f[i][j]表示从第i开始的五个动物状态压缩后(移走或不移走)为j的最优结果

那么转移方程可以得到

其中,val表示这一步转移所获得的收益,由于动物园是环形的,所以初状态等于末状态,我们枚举末状态,取出最大值即可

Code

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 inline int read() {
 5     int ret = 0;
 6     int op = 1;
 7     char c = getchar();
 8     while (c < '0' || c > '9') {if (c == '-') op = -1; c = getchar();}
 9     while (c <= '9' && c >= '0') ret = ret * 10 + c - '0', c = getchar();
10     return ret * op;
11 }
12 int n, m, ans;
13 int f[10010][1 << 6], val[10010][1 << 6];
14 int main() {
15     n = read(); m = read();
16     for (int i = 1; i <= m; ++i) {
17         int a = read(), b = read(), c = read();
18         int x = 0, y = 0, now;
19         for (int j = 1; j <= b; ++j) {
20             now = read();
21             now = (now - a + n) % n;
22             x |= 1 << now;
23         }
24         for (int j = 1; j <= c; ++j) {
25             now = read();
26             now = (now - a + n) % n;
27             y |= 1 << now;
28         }
29         for (int j = 0; j < (1 << 5); ++j)
30             if ((j & x) || ((~j) & y)) val[a][j]++;
31     }
32     for (int i = 0; i < (1 << 5); ++i) {
33         memset(f[0], 128, sizeof(f[0]));
34         f[0][i] = 0;
35         for (int j = 1; j <= n; ++j) {
36             for (int s = 0; s < (1 << 5); ++s)
37                 f[j][s] = max(f[j - 1][(s & 15) << 1], f[j - 1][(s & 15) << 1 | 1]) + val[j][s];
38         }
39         ans = max(ans, f[n][i]);
40     }
41     printf("%d\n", ans);
42     return 0;
43 }
AC Code

猜你喜欢

转载自www.cnblogs.com/shl-blog/p/11131361.html