題意:
給n個有序整數對ai bi,你需要選擇一些整數對 使得所有你選定的數的ai+bi的和最大。並且要求你選定的數對的ai之和非負,bi之和非負。
輸入格式
輸入的第一行為n,數對的個數
以下n行每行兩個整數 ai bi
以下n行每行兩個整數 ai bi
輸出格式
輸出你選定的數對的ai+bi之和
樣例輸入
5
-403 -625
-847 901
-624 -708
-293 413
886 709
-403 -625
-847 901
-624 -708
-293 413
886 709
樣例輸出
1715
數據規模和約定
1<=n<=100
-1000<=ai,bi<=1000
-1000<=ai,bi<=1000
思路:
不直接計算選定的數的ai+bi的和,而是轉化為計算在ai的和一定的情況下盡量使選定的bi的和最大。於是變成為一個和01背包差不多的問題。首先過濾掉所有ai和bi均小於0的數對,令dp[i][j]表示前i個數對,選定的ai的和為j的情況下bi的和的最大值,將dp[i][j]初始化為-INF,再將所有已知合法情況初始化:dp[i][a[i]] = b[i],之后dp[i][j] = max(dp[i - 1][j], dp[i][j]),若j - a[i]存在,dp[i][j] = max(dp[i][j], dp[i - 1][j - a[i]] + b[i])。為避免負數作為數組下標,要加一個偏移量。
實現:
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 using namespace std; 5 6 const int INF = 0x3f3f3f3f; 7 const int t = 100000; 8 int a[105], b[105], dp[105][200005], n, p, q; 9 int solve(int n) 10 { 11 for (int i = 0; i < n; i++) 12 { 13 for (int j = -t; j <= t; j++) 14 { 15 dp[i][j + t] = -INF; 16 } 17 } 18 for (int i = 0; i < n; i++) 19 dp[i][a[i] + t] = b[i]; 20 for (int i = 1; i < n; i++) 21 { 22 for (int j = -t; j <= t; j++) 23 { 24 dp[i][j + t] = max(dp[i - 1][j + t], dp[i][j + t]); 25 if (j + t - a[i] < 0 || j + t - a[i] > 200000) 26 continue; 27 dp[i][j + t] = max(dp[i][j + t], dp[i - 1][j + t - a[i]] + b[i]); 28 } 29 } 30 int ans = -INF; 31 for (int j = 0; j <= t; j++) 32 { 33 ans = max(ans, dp[n - 1][j + t] >= 0 ? j + dp[n - 1][j + t] : -INF); 34 } 35 return ans; 36 } 37 38 int main() 39 { 40 cin >> n; 41 int cnt = 0; 42 for (int i = 0; i < n; i++) 43 { 44 cin >> p >> q; 45 if (p < 0 && q < 0) 46 continue; 47 a[cnt] = p; 48 b[cnt++] = q; 49 } 50 int ans = solve(cnt); 51 if (ans <= -INF) 52 cout << "0" << endl; 53 else 54 cout << ans << endl; 55 return 0; 56 }