http://acm.hdu.edu.cn/showproblem.php?pid=1171
题意:有n种物品,给出每种物品的价值和数目,要将这些物品尽可能的分成相等的两份A和B且A>=B ,输出A,B。
母函数可以过,但感觉最直接的方法应该是多重背包。
母函数的话,也是按总价值的一半求,从一半到小枚举,直到找到系数不为0的就是B。
#include <stdio.h> #include <iostream> #include <map> #include <set> #include <stack> #include <vector> #include <math.h> #include <string.h> #include <queue> #include <string> #include <stdlib.h> #include <algorithm> #define LL long long #define _LL __int64 #define eps 1e-12 #define PI acos(-1.0) using namespace std; int main() { int n; int val[55],num[55]; int sum; int c1[125010],c2[125010]; while(~scanf("%d",&n)) { if(n < 0) break; sum = 0; for(int i = 1; i <= n; i++) { cin >> val[i] >> num[i]; sum += val[i]*num[i]; } int tmp = sum/2; memset(c1,0,sizeof(c1)); memset(c2,0,sizeof(c2)); for(int i = 0; i <= val[1]*num[1]; i += val[1]) c1[i] = 1; for(int i = 2; i <= n; i++) { for(int j = 0; j <= tmp; j++) { for(int k = 0; k+j <= tmp && k <= val[i]*num[i]; k += val[i]) c2[k+j] += c1[j]; } for(int j = 0; j <= tmp; j++) { c1[j] = c2[j]; c2[j] = 0; } } int i; for(i = tmp; i >= 0; i--) if(c1[i] != 0) break; printf("%d %d\n",sum-i,i); } return 0; }
多重背包,按总价值的一半进行背包,相比母函数时间更快,一维的相比二维的时间更快。
未优化的多重背包:
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; int val[55],num[55]; int dp[125010]; int n; int main() { while(~scanf("%d",&n)) { if(n < 0) break; int sum = 0; for(int i = 1; i <= n; i++) { scanf("%d %d",&val[i],&num[i]); sum += val[i]*num[i]; } int tmp = sum/2; memset(dp,0,sizeof(dp)); dp[0] = 1; int ans = -1; for(int i = 1; i <= n; i++) { for(int j = 0; j <= num[i]; j++) { for(int v = tmp; v >= j*val[i]; v--) //逆序 if(dp[v-j*val[i]]) { dp[v] = 1; ans = max(ans,v); } } } printf("%d %d\n",sum-ans,ans); } return 0; }
hdu 1171 Big Event in HDU(母函数|多重背包),布布扣,bubuko.com
hdu 1171 Big Event in HDU(母函数|多重背包)
原文地址:http://blog.csdn.net/u013081425/article/details/38177331