HDU1171母函数
Posted wx62be51b466b43
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU1171母函数相关的知识,希望对你有一定的参考价值。
1.题目链接。题意就是给你一些物品,这些物品有价值和数量,将他们分成两堆,尽可能的均分(二者之差尽可能的小)。前边我们分析过了,这可以使用背包解决,但是我们使用母函数也是可以解决的,本质上来说二者的区别不是很大,都是再一堆物品中选出一些合适的东西来,都是组合的思想。我们知道,再母函数的代码里面,我们有一层的循环是这样子写的:
for (i = 1; i<n; ++i)
for (j = 0; j <= limit; ++j)
for (k = 0; k <= m[i] && j + k * p[i] <= limit; ++k)
if (tmp[j + k * p[i]] || ans[j])
tmp[j + k * p[i]] = true;
其中第二层循环那个limit是我们所有物品加起来二点最大值,其实就是指数的最大值,既然是这样,我们就修改这里就可以了,修改成最大值的一般即可。然后再寻找答案的时候,我们找距离这个最近的系数。注意这里我们只是要下标。为什么?因为我们知道,我们在做完多项式的乘法之后:a[i]这个东西,意义有很多,不仅仅是第i项的系数,而且x的指数也是i所以,我们又知道,指数就是我们组合出来的物品的价值。所以,疑问解决。代码奉上:
using namespace std;
const int MAX = 1e6 + 10;
int ans[MAX], tmp[MAX], n, m[MAX], p[MAX];
void work(int limit)
int i, j, k;
memset(ans, 0, sizeof(ans));
memset(tmp, 0, sizeof(tmp));
for (i = 0; i <= m[0]; ++i)
ans[i*p[0]] = true;
for (i = 1; i<n; ++i)
for (j = 0; j <= limit; ++j)
for (k = 0; k <= m[i] && j + k * p[i] <= limit; ++k)
if (tmp[j + k * p[i]] || ans[j])
tmp[j + k * p[i]] = true;
for (j = 0; j <= limit; ++j)
ans[j] = tmp[j];
tmp[j] = false;
int main()
while (scanf("%d", &n) && n>0)
int SUM = 0;
for (int i = 0; i < n; i++)
scanf("%d%d", &p[i], &m[i]);
SUM += p[i] * m[i];
work(SUM / 2);
for (int i = SUM / 2; i >= 0; i--)
if (ans[i])
int A = max(SUM - i, i);
int B = min(SUM - i, i);
printf("%d %d\\n", A, B);
break;
return 0;
以上是关于HDU1171母函数的主要内容,如果未能解决你的问题,请参考以下文章
HDU 1171 Big Event in HDU(母函数或01背包)