题目
思路
注意到重量只有 1 , 2 , 3 1,2,3 1,2,3 三种取值,这肯定可以作为突破口。
如果只有重量 1 , 2 1,2 1,2 就很好计算,可以贪心。重量为偶数,肯定是两个重量为 1 1 1 、一个重量为 2 2 2 作为基础单位。重量为奇数,一开始拿一个重量为 1 1 1 的,问题转化为上面的情形。
然后枚举重量为 3 3 3 的有多少个即可。复杂度 O ( n log n ) \mathcal O(n\log n) O(nlogn) ,瓶颈是排序(贪心过程)。
代码
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
inline int readint(){
int a; scanf("%d",&a); return a;
}
template < typename T >
void getMax(T&a,T b){ if(a < b) a = b; }
const int MaxN = 100005;
int a[4][MaxN];
long long dp[MaxN*3], s[MaxN*3];
int main(){
int n = readint(), m = readint();
for(int i=1; i<=n; ++i){
int w = readint();
a[w][++ a[w][0]] = readint();
}
for(int i=1; i<4; ++i)
sort(a[i]+1,a[i]+a[i][0]+1,greater<int>());
for(int i=1; i<=a[3][0]; ++i)
s[i*3] = s[i*3-3]+a[3][i];
int p[3] = {0,1,1}; dp[0] = 0;
for(int i=2; i<=m; i+=2){
int one = 0, two = 0;
if(p[1]+1 <= a[1][0])
one = a[1][p[1]]+a[1][p[1]+1];
if(p[2] <= a[2][0])
two = a[2][p[2]];
if(one >= two)
p[1] += 2, dp[i] = dp[i-2]+one;
else p[2] ++, dp[i] = dp[i-2]+two;
}
p[1] = 2, p[2] = 1; dp[1] = a[1][1];
for(int i=3; i<=m; i+=2){
int one = 0, two = 0;
if(p[1]+1 <= a[1][0])
one = a[1][p[1]]+a[1][p[1]+1];
if(p[2] <= a[2][0])
two = a[2][p[2]];
if(one >= two)
p[1] += 2, dp[i] = dp[i-2]+one;
else p[2] ++, dp[i] = dp[i-2]+two;
}
for(int i=1; i<=m; ++i){
getMax(dp[i],dp[i-1]);
getMax(s[i],s[i-1]);
}
long long ans = 0;
for(int i=0; i<=m; ++i)
getMax(ans,s[i]+dp[m-i]);
printf("%lld\n",ans);
return 0;
}