hdu6804 Contest Of Rope Pulling // DP

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6804

给出两个班的人,每个人具有力量与颜值两个属性。要求在两个班级中分别选取任意个人,使得各班力量总和相同,求总颜值的最大值。

01背包 ——>  取负优化

由于数据较大,直接求和的话我们的内存伤不起。

因而选择将一个班级同学的力量取负,转而求DP[0]的max。

又根据数组下标非负性,找个maxn再向右挪一波——> 求DP[mid]

参考文献:https://blog.csdn.net/qq_43346369/article/details/107723423?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param 

一寸长 一寸强

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<iomanip>
 6 #include<vector>
 7 #include<random>
 8 
 9 #define ll long long
10 #define INF 1ll << 62//
11 using namespace std;
12 const int maxn = 1e5 + 10;
13 //通过随机数组元素の顺序,达到缩小maxn的目的
14 //取(-5e4,5e4),原本答案位于dp[0],但由于dp数组的正号性,直接右移5e4,取maxn=1e5
15 struct node
16 {
17     ll u;
18     ll v;
19 };
20 
21 int n, m;
22 ll dp[maxn];
23 
24 int main(){
25     int T;cin >> T;
26     while(T--)
27     {
28         cin >> n >> m;
29         vector<node>v;
30         ll a, b;
31         for(int i = 1 ; i <= n ; i++){
32             scanf("%lld %lld",&a,&b);
33             v.push_back({a ,b});
34         }
35         for(int i = 1 ; i <= m ; i++){
36             scanf("%lld %lld",&a,&b);
37             v.push_back({-a ,b});
38         }//B班改为负
39 
40         random_shuffle(v.begin(),v.end());//数组随机化
41         for(int i = 0 ; i < maxn ; i++)    dp[i] = -INF;
42 
43         const int mid = 5e4;
44         dp[mid] = 0;
45         for(int i = 0 ; i < m + n ; i++){//vector从零开始
46             if(v[i].u > 0){//等号放在下面好像不行
47                 for(int j = mid * 2; j >= v[i].u ; j--){//j - v[i].u >= 0
48                     dp[j] = max(dp[j], dp[j - v[i].u] + v[i].v);
49                 }
50             }else if(v[i].u < 0){
51                 for(int j = 0 ; j <= mid * 2 + v[i].u ; j++){//j - v[i].u <= maxn
52                     dp[j] = max(dp[j], dp[j - v[i].u] + v[i].v);
53                 }
54             }else{//长得好看但没力气的人处处受欢迎。社会风气√
55                 for(int j = 0 ; j <= mid * 2 ; j++){
56                     dp[j] = max(dp[j], dp[j] + v[i].v);
57                 }
58             }
59             //正负两组分别向mid方向汇聚,- ... MID ... +
60         }
61 
62         printf("%lld
",dp[mid]);
63 
64     }
65 
66     return 0;
67 }
68 //数对是真好用
原文地址:https://www.cnblogs.com/ecustlegendn324/p/13498756.html