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所以,我们又知道,指数就是我们组合出来的物品的价值。所以,疑问解决。代码奉上:

#include<bits/stdc++.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAX = 1e6 + 10;
#pragma warning(disable:4996)
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背包)

hdu-1521 排列组合 指数型母函数

HDU1398物品无限的母函数

hdu1521 排列组合(指数型母函数)

HDU 1171 Big Event in HDU(0-1背包)

hdu 1171 Big Event in HDU