继续DP,N只有16位,状态压缩下,用整数表示背包状态,本题参考大神思路,先做预处理,把包含其他组合的组合去掉,比如说1,2,3,4和1,2两种组合,前面那种就可以去掉,因为选前面那种肯定不如后面那种。然后以方案数为值DP,背包大小从最大递减到最小,位操作想仔细点,不要弄错了。本以为会超时,竟然AC了。。真是稀里糊涂
#include<stdio.h>
#include<string.h>
static int max(int a, int b)
{
return a > b ? a : b;
}
int main()
{
int n, m, k, a[50001], dp[1 << 16];
while (scanf("%d %d", &n, &m) != EOF)
{
int i, j, temp, num, index = 0;
for (i = 0; i < m; i++)
{
scanf("%d", &k);
temp = 0;
while (k--)
{
scanf("%d", &num);
temp |= 1 << (num - 1);
}
for (j = 0; j < index; j++)
{
if ((a[j] & temp) == a[j])
break;
if ((a[j] & temp) == temp)
{
a[j] = temp;
break;
}
}
if (j == index)
a[index++] = temp;
}
memset(dp, 0, sizeof(dp));
for (i = 0; i < index; i++)
for (j = (1 << n) - 1; j >= 0; j--)
if ((j & a[i]) == a[i])
dp[j] = max(dp[j], dp[j - a[i]] + 1);
printf("%d\n", dp[(1 << n) - 1]);
}
return 0;
}