这题能不能贪心,是很难说的。。
因为没有能什么证明贪心是对的,但也没找到什么反例。
代码写出来,WA了。
但总觉得是对的,因为吗的实在找不到反例。
结果找到数据测了下,果然十个过了九个。。
你看,如果这是NOIP,跟满分都没啥区别的对吧。我已经满足了。。
没过的那组,比较大,肉眼看不出是啥问题。
想了下,给排序加多了一个判断,然后那组数据就过了。。
然后提交,吗的还上榜了。。无语。
这样做比较无耻,网上有人说用最大流做,不理解。下次想一想。
思路:
如果牛喜欢的种类个数小于 K,那这种牛是无法满足的。。
把牛按照喜欢的种类个数排序,先处理小的。
就是用组合数枚举每一种可能的 pizza 情况。
用 hash 保存这些情况。
代码:
#include <stdio.h>
#include <stdlib.h>
#define HASH_SIZE 65536
struct cow_node {
int val, cnt;
};
int C, T, K, ans;
struct cow_node cows[1024];
int hash[HASH_SIZE];
int cmp(const void *a, const void *b)
{
if (((struct cow_node *)a)->cnt == ((struct cow_node *)b)->cnt)
return ((struct cow_node *)a)->val - ((struct cow_node *)b)->val;
return ((struct cow_node *)a)->cnt - ((struct cow_node *)b)->cnt;
}
inline int insert(int val)
{
int i, h;
h = val & (HASH_SIZE - 1);
for (i = h + 1; i != h && hash[i] && hash[i] != val; )
i = (i + 1) & (HASH_SIZE - 1);
if (i == h || hash[i] == val)
return 0;
hash[i] = val;
return 1;
}
inline int calc(struct cow_node *t)
{
int arr[32], map[32], i, j, val;
for (i = j = 0; i < 32; i++)
if (t->val & (1 << i))
map[j++] = (1 << i);
for (i = 0; i < K; i++)
arr[i] = i;
while (1) {
val = 0;
for (i = 0; i < K; i++)
val |= map[arr[i]];
if (insert(val))
return 1;
for (i = K - 1; i >= 0 && arr[i] == i + t->cnt - K; i--);
if (i < 0)
break;
arr[i]++;
for (i++; i < K; i++)
arr[i] = arr[i - 1] + 1;
}
return 0;
}
int main()
{
int i, j, k;
freopen("e:\\test\\in.txt", "r", stdin);
scanf("%d%d%d", &C, &T, &K);
for (i = 0; i < C; i++) {
scanf("%d", &cows[i].cnt);
cows[i].val = 0;
for (j = 0; j < cows[i].cnt; j++) {
scanf("%d", &k);
k--;
cows[i].val |= 1 << k;
}
if (cows[i].cnt < K) {
i--; C--;
continue;
}
}
qsort(cows, C, sizeof(cows[0]), cmp);
for (i = 0; i < C; i++)
ans += calc(&cows[i]);
printf("%d\n", ans);
return 0;
}