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