RT,思路就是先看 w=1 或 2 的物品,直接贪心按性价比取,再看 w=3 的物品,对于前面取到的每一个重量,算剩下的重量放这些物品的最大价值。但是 WA 了。
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#define int long long
using namespace std;
void solve()
{
int n, m; scanf("%lld%lld", & n, & m);
vector < int > a, b, c;
for(int i = 0; i < n; i ++){
int w, v; scanf("%lld%lld", & w, & v);
if(w == 1) a.push_back(v);
if(w == 2) b.push_back(v);
if(w == 3) c.push_back(v);
}
sort(a.begin(), a.end()), reverse(a.begin(), a.end());
sort(b.begin(), b.end()), reverse(b.begin(), b.end());
sort(c.begin(), c.end()), reverse(c.begin(), c.end());
while((int)a.size() < m) a.push_back(0);
while((int)b.size() < m) b.push_back(0);
while((int)c.size() < m) c.push_back(0);
vector < int > sumc(m + 1);
for(int i = 1; i <= m; i ++) sumc[i] = sumc[i - 1] + c[i - 1];
int ans = max(sumc[m / 3], a[0] + sumc[(m - 1) / 3]), cnt = 0, sum = 0, ia = 0, ib = 0;
while(true){
if(a[ia] + a[ia + 1] > b[ib]) cnt += 2, sum += a[ia] + a[ia + 1], ia += 2;
else cnt += 2, sum += b[ib], ib ++;
if(cnt > m) break;
ans = max(ans, sum + sumc[(m - cnt) / 3]);
if(cnt + 1 <= m) ans = max(ans, sum + a[ia] + sumc[(m - cnt - 1) / 3]);
}
printf("%lld\n", ans);
}
signed main()
{
int t = 1;
while(t --) solve();
return 0;
}