题目链接
http://acm.hdu.edu.cn/showproblem.php?pid=1171
题意
老师有一个属性:价值(value)。在学院里的老师共有n种价值,每一种价值value对应着m个老师,说明这m个老师的价值都为value。现在要将这些老师从人数上平分成两个院系,并且希望平分后两个院系老师的总价值A和B应尽可能地相等,求A和B的值(A>=B)。
思路
由于每种老师的个数是有限的,所以使用多重背包解决。由于测试数据不是很严格,所以使用01背包也可以通过。
代码
01背包:
1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 using namespace std; 6 7 const int N = 5010; 8 const int M = 50 * 5000; 9 int v[N]; 10 int dp[M]; 11 12 int main() 13 { 14 //freopen("hdoj1171.txt", "r", stdin); 15 int n; 16 while (cin >> n && n >= 0) 17 { 18 int cur = 0; //记录教师总数 19 int sum = 0; //记录教师总价值 20 for (int i = 0;i < n; i++) 21 { 22 int val, m; 23 cin >> val >> m; 24 for (int j = 0; j < m; j++) 25 { 26 v[cur++] = val; 27 sum += val; 28 } 29 } 30 31 memset(dp, 0, sizeof(dp)); 32 for (int i = 0; i < cur; i++) 33 { 34 for (int j = sum / 2; j >= v[i]; j--) 35 dp[j] = max(dp[j], dp[j - v[i]] + v[i]); //weight和value相同 36 } 37 //由于dp[sum/2]<sum/2,所以dp[sum/2]一定是较小者,sum - dp[sum / 2]是较大者 38 cout << sum - dp[sum / 2] << " " << dp[sum / 2] << endl; 39 } 40 return 0; 41
多重背包:
1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 using namespace std; 6 7 const int N = 110; 8 const int M = 50 * 5000; 9 int v[N], num[N]; 10 int dp[M]; 11 int sum; 12 13 void zero_one_pack(int weight, int value, int capacity) 14 { 15 for (int i = capacity; i >= weight; i--) //逆序 16 dp[i] = max(dp[i], dp[i - weight] + value); 17 } 18 19 void complete_pack(int weight, int value, int capacity) 20 { 21 for (int i = weight; i <= capacity; i++) //正序 22 dp[i] = max(dp[i], dp[i - weight] + value); 23 } 24 25 void mutiple_pack(int weight, int value, int amount, int capacity) 26 { 27 if (weight*amount >= capacity) 28 complete_pack(weight, value, capacity); 29 else 30 { 31 int k = 1; 32 while (k <= amount) 33 { 34 zero_one_pack(weight*k, value*k, capacity); 35 amount -= k; 36 k *= 2; 37 } 38 zero_one_pack(weight*amount, value*amount, capacity); 39 } 40 41 } 42 43 int main() 44 { 45 //freopen("hdoj1171.txt", "r", stdin); 46 int n; 47 while (cin >> n && n >= 0) 48 { 49 sum = 0; 50 for (int i = 1; i <= n; i++) 51 { 52 cin >> v[i] >> num[i]; 53 sum += v[i] * num[i]; 54 } 55 56 memset(dp, 0, sizeof(dp)); 57 for (int i = 1; i <= n; i++) 58 mutiple_pack(v[i], v[i], num[i], sum / 2); 59 60 cout << sum - dp[sum / 2] << " " << dp[sum / 2] << endl; 61 } 62 }
时间: 2024-10-04 15:05:00