题意:
有N个物品,每个物品有重量(1,2,3)和价值c。
现在问总重量小于等于m的最大价值?
m <= 3e5, n <= 2e5
题解:
背包问题数据加大版,但是重量的种数只有3种。
想DP却无从下手。
其实枚举即可。
枚举重量为3的个数,三分重量为2的个数,就做完了。。
还有一种DP的做法,当然还是枚举3的个数,然后dp[i]代表只用1, 2的重量时最大价值,DP的正确性我不能证明。
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <bitset>
#include <map>
#include <vector>
#include <stack>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <cmath>
#include <ctime>
#ifdef LOCAL
#define debug(x) cout<<#x<<" = "<<(x)<<endl;
#else
#define debug(x) 1;
#endif
#define chmax(x,y) x=max(x,y)
#define chmin(x,y) x=min(x,y)
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
#define lowbit(x) x&-x
#define mp make_pair
#define pb push_back
#define fir first
#define sec second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, int> pii;
const int MOD = 1e9 + 7;
const double PI = acos (-1.);
const double eps = 1e-10;
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3f;
const int MAXN = 3e5 + 5;
vector<ll> v[4];
ll pre[4][MAXN];
int cmp (int x, int y) {
return x > y;
}
int n, m;
int n3;
ll calc (int n2) {
return pre[2][n2] + pre[1][m - 2 * n2 - 3 * n3];
}
ll solve (int l, int r) {
while (l < r) {
int m1 = floor (1.0 * (2 * l + r) / 3), m2 = floor (1.0 * (l + 2 * r + 2) / 3);
if (calc (m1) < calc (m2) ) l = m1 + 1;
else r = m2 - 1;
}
ll vl = calc (l), vr = calc (r);
return max (vr, vl);
}
int w[MAXN], c[MAXN];
int main() {
#ifdef LOCAL
freopen ("input.txt", "r", stdin);
#endif
scanf ("%d %d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf ("%d %d", &w[i], &c[i]);
v[w[i]].pb (c[i]);
}
for (int i = 1; i <= 3; i++) sort (v[i].begin(), v[i].end(), cmp);
for (int i = 1; i <= 3; i++) {
for (int j = 0; j < v[i].size(); j++)
pre[i][j + 1] = pre[i][j] + v[i][j];
for (int j = v[i].size(); j < MAXN - 1; j++)
pre[i][j + 1] = pre[i][j];
}
ll ans = 0;
for (int i = 0; i <= v[3].size(); i++) {
n3 = i;
if (i * 3 > m) break;
ans = max (ans, pre[3][i] + solve (0, (m - 3 * i) / 2) );
}
printf ("%lld\n", ans);
return 0;
}