题意:
样例:
2
10 1
20 1
意思是两种物品,质量为10的物品有一个,质量为20的物品有一个,求如何分使得最大程度的两等分?
答案当然是 : 20 10 (题目规定大的放前面)
3
10 1
20 2
30 1
意思是三种物品,质量为10的物品有一个,质量为20的物品有两个,,质量为30的物品有一个,求如何分使得最大程度的两等分?
答案当然是 : 40 40 即20 20放一起 、10 30 放一起即可
分析:本题我采用多重背包转01背包的做法,把输入的物品质量放入a数组,如果物品数量大于1,就放多次,当然可以二进制优化,但在本题中不优化也可以AC。
另外注意判断输入结束必须是t<0 ,而不是t==-1!!!
另外注意判断输入结束必须是t<0 ,而不是t==-1!!!
另外注意判断输入结束必须是t<0 ,而不是t==-1!!!
当然下面就是01背包的模板
for i=1..N
for v=V..0
f[v]=max{f[v],f[v-c[i]]+w[i]};
在本题中,第一层遍历物品的个数N,第二层遍历背包容量sum/2,状态转移方程一套就可以了。
注意dp数组的初始化,还有输出大的放前面即可。
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int a[5002];
int dp[500002];
int maxx(int x, int y) {
return x > y ? x : y;
}
int main()
{
int t;
while (~scanf_s("%d", &t) && t >= 0) {
int len = 0;
int sum = 0;
while (t--) {
int x, y;
scanf_s("%d%d", &x, &y);
sum += x * y;
while (y--) {
a[len++] = x;
}
}
int summ = sum;
sum /= 2;
memset(dp, 0, sizeof(dp));
for (int i = 0; i < len; i++) {
for (int j = sum; j >= a[i]; j--) {
dp[j] = maxx(dp[j], dp[j - a[i]] + a[i]);
}
}
printf("%d %d\n", summ - dp[sum], dp[sum]);
}
return 0;
}