hdu6804 Contest Of Rope Pulling // DP
阿新 • • 發佈:2020-08-13
題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=6804
給出兩個班的人,每個人具有力量與顏值兩個屬性。要求在兩個班級中分別選取任意個人,使得各班力量總和相同,求總顏值的最大值。
01揹包 ?——> 取負優化
由於資料較大,求和的話我們的記憶體傷不起。
因而選擇將一個班級同學的力量取負,轉而求DP[0]的max。
又根據陣列下標非負性,找個maxn再向右挪一波——> 求DP[mid]
一寸長 一寸強
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\n",dp[mid]);
63
64 }
65
66 return 0;
67 }
68 //數對是真好用