BZOJ1688:状压DP裸题,只要将普通背包DP的容量,变为01串即可。
核心DP转移片段:
// Author: 23forever
#include <bits/stdc++.h>
#define mp make_pair
#define fi first
#define se second
typedef long long LL;
const int MAXN = 200000;
using namespace std;
inline int read() {
int x = 0, w = 1;
char c = ' ';
while (c < '0' || c > '9') {
c = getchar();
if (c == '-') w = -1;
}
while (c >= '0' && c <= '9') {
x = (x << 1) + (x << 3) + (c ^ 48);
c = getchar();
}
return x * w;
}
int n, d, k, dp[1 << 15], c[MAXN + 5];
void init() {
n = read();
d = read();
k = read();
for (int i = 1; i <= n; ++i) {
int t = read();
for (int j = 1; j <= t; ++j) {
int x = read();
c[i] |= (1 << (x - 1));
}
}
}
bitset<15> B;
int main() {
#ifdef forever23
freopen("test.in", "r", stdin);
freopen("test.out", "w", stdout);
#endif
init();
int N = 1 << d;
for (int i = 1; i <= n; ++i) {
for (int cur_state = N - 1; ~cur_state; --cur_state) {
int nxt_state = cur_state | c[i];
dp[nxt_state] = max(dp[nxt_state], dp[cur_state] + 1);
}
}
int ans = 0;
for (int s = 0; s < N; ++s) {
B = s;
if (B.count() <= k) ans = max(ans, dp[s]);
}
printf("%d\n", ans);
return 0;
}