題目連結:http://codeforces.com/problemset/problem/366/C
題意:
有n個物品,每個物品有兩個屬性a[i]和b[i]。
給定k,讓你選出一些物品,使得 ∑ a[i] / ∑ b[i] = k。
問你選出物品的 ∑ a[i]最大是多少。
題解:
將原式變形:
∑ a[i] - k * ∑ b[i] = 0
可以看做有一個容積為0的箱子,每個物品的價值為a[i],體積為a[i] - k*b[i],問你最大總價值。
這就變成了01揹包。
但是體積a[i] - k*b[i]有可能為負值。
所以將體積為正的分一堆,體積為負的分到另一堆。
體積取絕對值,分別跑一遍01揹包求出pos陣列和neg陣列。
pos[i]和neg[i]分別表示用了i的體積,此時的最大總價值。
然後統計答案。
列舉花費體積i,正負相互抵消:ans = max(pos[i] + neg[i])
當ans = 0時說明啥都沒選,輸出-1。
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #define MAX_N 105 5 #define MAX_C 100005 6 7 using namespace std; 8 9 int n,k; 10 int a[MAX_N]; 11 int b[MAX_N]; 12 int pos[MAX_C]; 13 int neg[MAX_C]; 14 15 void read() 16 { 17 cin>>n>>k; 18 for(int i=1;i<=n;i++) cin>>a[i]; 19 for(int i=1;i<=n;i++) cin>>b[i]; 20 } 21 22 void work() 23 { 24 memset(pos,0xc0,sizeof(pos)); 25 memset(neg,0xc0,sizeof(neg)); 26 pos[0]=neg[0]=0; 27 for(int i=1;i<=n;i++) 28 { 29 int c=a[i]-k*b[i]; 30 if(c>=0) 31 { 32 for(int j=MAX_C-1;j>=c;j--) 33 { 34 pos[j]=max(pos[j],pos[j-c]+a[i]); 35 } 36 } 37 else 38 { 39 c=-c; 40 for(int j=MAX_C-1;j>=c;j--) 41 { 42 neg[j]=max(neg[j],neg[j-c]+a[i]); 43 } 44 } 45 } 46 int ans=0; 47 for(int i=0;i<MAX_C;i++) 48 { 49 ans=max(ans,pos[i]+neg[i]); 50 } 51 if(ans) cout<<ans<<endl; 52 else cout<<-1<<endl; 53 } 54 55 int main() 56 { 57 read(); 58 work(); 59 }