Codeforces 366C Dima and Salad:背包dp

题目链接: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 }

 

posted @ 2018-01-03 12:35  Leohh  阅读(328)  评论(0编辑  收藏  举报