您的位置:首页 > 其它

hdoj1171 Big Event in HDU(01背包 || 多重背包)

2017-12-09 22:41 387 查看

题目链接

http://acm.hdu.edu.cn/showproblem.php?pid=1171

题意

老师有一个属性:价值(value)。在学院里的老师共有n种价值,每一种价值value对应着m个老师,说明这m个老师的价值都为value。现在要将这些老师从人数上平分成两个院系,并且希望平分后两个院系老师的总价值A和B应尽可能地相等,求A和B的值(A>=B)。

思路

由于每种老师的个数是有限的,所以使用多重背包解决。由于测试数据不是很严格,所以使用01背包也可以通过。

代码

01背包:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;

const int N = 5010;
const int M = 50 * 5000;
int v
;
int dp[M];

int main()
{
//freopen("hdoj1171.txt", "r", stdin);
int n;
while (cin >> n && n >= 0)
{
int cur = 0;    //记录教师总数
int sum = 0;    //记录教师总价值
for (int i = 0;i < n; i++)
{
int val, m;
cin >> val >> m;
for (int j = 0; j < m; j++)
{
v[cur++] = val;
sum += val;
}
}

memset(dp, 0, sizeof(dp));
for (int i = 0; i < cur; i++)
{
for (int j = sum / 2; j >= v[i]; j--)
dp[j] = max(dp[j], dp[j - v[i]] + v[i]);    //weight和value相同
}
//由于dp[sum/2]<sum/2,所以dp[sum/2]一定是较小者,sum - dp[sum / 2]是较大者
cout << sum - dp[sum / 2] << " " << dp[sum / 2] << endl;
}
return 0;

多重背包:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;

const int N = 110;
const int M = 50 * 5000;
int v
, num
;
int dp[M];
int sum;

void zero_one_pack(int weight, int value, int capacity)
{
for (int i = capacity; i >= weight; i--)    //逆序
dp[i] = max(dp[i], dp[i - weight] + value);
}

void complete_pack(int weight, int value, int capacity)
{
for (int i = weight; i <= capacity; i++)    //正序
dp[i] = max(dp[i], dp[i - weight] + value);
}

void mutiple_pack(int weight, int value, int amount, int capacity)
{
if (weight*amount >= capacity)
complete_pack(weight, value, capacity);
else
{
int k = 1;
while (k <= amount)
{
zero_one_pack(weight*k, value*k, capacity);
amount -= k;
k *= 2;
}
zero_one_pack(weight*amount, value*amount, capacity);
}

}

int main()
{
//freopen("hdoj1171.txt", "r", stdin);
int n;
while (cin >> n && n >= 0)
{
sum = 0;
for (int i = 1; i <= n; i++)
{
cin >> v[i] >> num[i];
sum += v[i] * num[i];
}

memset(dp, 0, sizeof(dp));
for (int i = 1; i <= n; i++)
mutiple_pack(v[i], v[i], num[i], sum / 2);

cout << sum - dp[sum / 2] << " " << dp[sum / 2] << endl;
}
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: