演算法提高 求最大值
時間限制:1.0s 記憶體限制:256.0mb
問題描述
給n個有序整數對ai bi,你需要選擇一些整數對 使得所有你選定的數的ai+bi的和最大。並且要求你選定的數對的ai之和非負,bi之和非負。
輸入格式
輸入的第一行為n,數對的個數
以下n行每行兩個整數 ai bi
輸出格式
輸出你選定的數對的ai+bi之和
樣例輸入 5
-403 -625
-847 901
-624 -708
-293 413
886 709
樣例輸出
1715
資料規模和約定
1<=n<=100
-1000<=ai,bi<=1000
話不多說開始動規,dp[i][j],i表示前i個數對,j表示所採取的數對的ai之和,dp[i][j]表示對應的bi之和。
首先考慮乙個問題,題目要求的是ai之和非負,bi之和非負,還有乙個隱藏的條件是,如果乙個數對都不挑選的話,那麼對應的結果應該是0。
所以我們考慮在輸入期間就把ai為負值,bi也為負值的數對全部去除,因為一旦用到他們肯定不會是最優解。
狀態方程:dp[i][j]=max(dp[i-1][j-ai]+bi,dp[i][j]); j-ai是為了得到當沒有加入ai時對應的dp值,所以dp[i-1][j-ai]+bi就是加入ai得到的dp值。對某乙個狀態來說,dp[i][j]+j就是他們的ai與bi之和。
將ai值和bi值偏移為正值之後的確就是乙個很顯然的揹包問題。
需要注意的事,這題的狀態轉移比普通的揹包要嚴苛得多。
在揹包問題中,我們說在第i次選擇時,當前狀態dp[i][j]可以由兩個狀態轉移而來,乙個是dp[i][v-1],乙個是dp[i-1][v-v[i]],但是在此題中只能是dp[i-1][j]和dp[i-1][j-a[i]]轉移而來,直接承接上一行的值是因為,j表示的是ai之和,是限定死的。
#include
#define min 0x8f000000
using namespace std;
int n,a[105],b[105],dp[105][200005],pe=100000;//pe為偏移量 題目要求上限100個數,數值上下限為+ -1000,所以總區間長度為200000
int main()
a[++ans]=p;
b[ans]=q;
}for(int j=1;j<=ans;j++)
}for(int o=1;o<=ans;o++)
for(int u=2;u<=ans;u++)
} int temp=min;
for(int y=0;y<=pe;y++)//也就是說在左端的值並沒有進行考慮,在左端的值,就是ai之和為負值的情況
if(temp==min1)
else cout}唯一可能的問題是,為什麼明明有偏移量,最後只需要乙個dp[ans][y+pe]+y即可得到答案。
理由如下:實際上我們僅僅在
for(int o=1;o<=ans;o++)
這裡初始化的時候加了偏移量,在此之後的狀態轉移過程中,並沒有再加偏移量,回到狀態dp的定義,dp[i][j]表示的是在前i個數對中選擇,選擇得到的數對的ai之和為j,狀態中存入的量為對應的bi之和。
dp[i][j+pe],j+pe僅僅是為了避免加上負值的ai導致越界而製造的偏移罷了,所以j+dp[i][j+pe]就是最終解。
至於為什麼最後的解落在dp[n][0+pe]~dp[n][pe+pe],想必已經很明顯了吧,題目要求ai之和非負,若是在dp[n][0]~dp[n][pe],減去偏移量後,對應的ai之和是負值,因此無須考慮。
試題 演算法提高 求最大值
時間限制 1.0s 記憶體限制 256.0mb 問題描述 給n個有序整數對ai bi,你需要選擇一些整數對 使得所有你選定的數的ai bi的和最大。並且要求你選定的數對的ai之和非負,bi之和非負。輸入格式 輸入的第一行為n,數對的個數 以下n行每行兩個整數 ai bi 輸出格式 輸出你選定的數對的...
藍橋杯 演算法提高 求最大值
演算法提高 求最大值 時間限制 1.0s 記憶體限制 256.0mb 問題描述 給n個有序整數對ai bi,你需要選擇一些整數對 使得所有你選定的數的ai bi的和最大。並且要求你選定的數對的ai之和非負,bi之和非負。輸入格式 輸入的第一行為n,數對的個數 以下n行每行兩個整數 ai bi 輸出格...
藍橋杯 演算法提高 求最大值
演算法提高 求最大值 時間限制 1.0s 記憶體限制 256.0mb 問題描述 給n個有序整數對ai bi,你需要選擇一些整數對 使得所有你選定的數的ai bi的和最大。並且要求你選定的數對的ai之和非負,bi之和非負。輸入格式 輸入的第一行為n,數對的個數 以下n行每行兩個整數 ai bi 輸出格...