2020ICPC·小米 网络选拔赛第二场 H Knapsack(超大01背包)

链接:https://ac.nowcoder.com/acm/contest/7502/H
来源:牛客网
 

时间限制:C/C++ 3秒,其他语言6秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

Bobo has n items, where the i-th item has weight wiw_iwi​ and value viv_ivi​. He wants to pick some items whose sum of weights does not exceed m, and maximize the sum of values.

输入描述:

The input consists of several test cases terminated by end-of-file.

The first line of each test case contains two integers n and m. The i-th of the following n lines contains two integers wiw_iwi​ and viv_ivi​.

* 1≤n≤2×1051 \leq n \leq 2 \times 10^51≤n≤2×105
* 1≤m≤2×1051 \leq m \leq 2 \times 10^51≤m≤2×105
* 1≤wi≤1001 \leq w_i \leq 1001≤wi​≤100
* 1≤vi≤1091 \leq v_i \leq 10^91≤vi​≤109
* The sum of n does not exceed 10610^6106.
* The sum of m does not exceed 10610^6106.

输出描述:

For each test case, print an integer which denotes the result.

示例1

输入

3 4
1 1
2 2
2 3
3 5
1 1
2 2
2 3
1 10
9 1000000000

输出

5
6
1000000000

容量和价值都超大的01背包

要使答案最优,价值和容量比值大的物品一定会取(不用管,直接加到答案里),比值小的再用普通01背包求解

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 2e5 + 7;
const ll mod = 1e9 + 7;
const ll inf = 0x3f3f3f3f;
const ll ninf = 0xc0c0c0c0;

ll n, m;
struct node {
    ll w, v;
} s[N];

bool cmp(node a, node b) {
    return a.w * b.v < a.v * b.w;
}

ll dp[1105];

int main() {
    while(~scanf("%lld%lld", &n, &m)) {
        for(ll i = 1; i <= n; ++i) {
            scanf("%lld%lld", &s[i].w, &s[i].v);
        }
        sort(s + 1, s + n + 1, cmp);
        ll id;
        ll ans = 0;
        for(id = 1; id <= n && m >= 1000; ++id) {
            ans += s[id].v;
            m -= s[id].w;
        }
        memset(dp, 0, sizeof(dp));
        for(; id <= n; ++id)
            for(ll j = m; j >= s[id].w; --j)
                dp[j] = max(dp[j], dp[j - s[id].w] + s[id].v);
        printf("%lld\n", ans + dp[m]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43871207/article/details/109498808