1. 程式人生 > 實用技巧 >hdu6804 Contest Of Rope Pulling // DP

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\n",dp[mid]); 63 64 } 65 66 return 0; 67 } 68 //數對是真好用