E - Knapsack 2


Time Limit: 2 sec / Memory Limit: 1024 MB

Score : <var>100100</var> points

Problem Statement

There are <var>NN</var> items, numbered <var>1,2,,N1,2,…,N</var>. For each <var>ii</var> (<var>1iN1≤i≤N</var>), Item <var>ii</var> has a weight of <var>wiwi</var> and a value of <var>vivi</var>.

Taro has decided to choose some of the <var>NN</var> items and carry them home in a knapsack. The capacity of the knapsack is <var>WW</var>, which means that the sum of the weights of items taken must be at most <var>WW</var>.

Find the maximum possible sum of the values of items that Taro takes home.

Constraints

  • All values in input are integers.
  • <var>1N1001≤N≤100</var>
  • <var>1W1091≤W≤109</var>
  • <var>1wiW1≤wi≤W</var>
  • <var>1vi1031≤vi≤103</var>

Input

Input is given from Standard Input in the following format:

<var>NN</var> <var>WW</var>
<var>w1w1</var> <var>v1v1</var>
<var>w2w2</var> <var>v2v2</var>
<var>::</var>
<var>wNwN</var> <var>vNvN</var>

Output

Print the maximum possible sum of the values of items that Taro takes home.


Sample Input 1 Copy

Copy
3 8
3 30
4 50
5 60

Sample Output 1 Copy

Copy
90

Items <var>11</var> and <var>33</var> should be taken. Then, the sum of the weights is <var>3+5=83+5=8</var>, and the sum of the values is <var>30+60=9030+60=90</var>.


Sample Input 2 Copy

Copy
1 1000000000
1000000000 10

Sample Output 2 Copy

Copy
10

Sample Input 3 Copy

Copy
6 15
6 5
5 6
6 4
6 6
3 5
7 2

Sample Output 3 Copy

Copy
17

Items <var>2,42,4</var> and <var>55</var> should be taken. Then, the sum of the weights is <var>5+6+3=145+6+3=14</var>, and the sum of the values is <var>6+6+5=176+6+5=17</var>.

题目链接:https://atcoder.jp/contests/dp/tasks/dp_e

思路:体积虽然很huge,但价值很小。把最大化价值,转成最小化体积,就还是原来的01背包了。(RUSH_D_CAT大佬指点的

很不错的一个背包优化的思路,细节见我的代码。

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
using namespace std;
typedef long long ll;
inline void getInt(int* p);
const int maxn=1000010;
const int inf=0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
ll dp[maxn];
ll n,W;
ll v[maxn];
ll w[maxn];
int main()
{
    memset(dp,0x3f,sizeof(dp));
    gbtb;
    cin>>n>>W;
    repd(i,1,n)
    {
        cin>>w[i]>>v[i];
    }
    ll ans=0ll;
    dp[0]=0;
    repd(i,1,n)
    {
        for(int j=1e5;j>=v[i];--j)
        {
            {
                dp[j]=min(dp[j],dp[j-v[i]]+w[i]);
                if(dp[j]<=W)
                    ans=max(ans,(ll)(j));
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}

inline void getInt(int* p) {
    char ch;
    do {
        ch = getchar();
    } while (ch == ' ' || ch == '\n');
    if (ch == '-') {
        *p = -(getchar() - '0');
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 - ch + '0';
        }
    }
    else {
        *p = ch - '0';
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 + ch - '0';
        }
    }
}