题目链接:https://ac.nowcoder.com/acm/contest/7502/H
分析
这题如果直接用背包做的话会超时,因为 w 的范围非常小,所以算法的复杂度会很大。
既然 w 很小,那么我们可以先贪心,根据每一个单位的价值来排序,前面的可以直接放进包里,从而达到缩小 dp 范围的目的。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,m;
struct node{
ll w;
ll v;
}a[1000007];
ll f[200007];
int cmp(node x, node y)
{
double v1 = 1.0 * x.v / x.w;
double v2 = 1.0 * y.v / y.w;
return v1 > v2;
}
int main()
{
while(~scanf("%lld%lld",&n,&m))
{
for(int i=0;i<=m;i++) f[i] = 0;
for(int i=1;i<=n;i++)
scanf("%lld%lld",&a[i].w,&a[i].v);
sort(a + 1, a + 1 + n, cmp);
int p = 1;
ll ans = 0;
while(p <= n && m >= 500)
{
ans += a[p].v;
m -= a[p].w;
p++;
}
for(int i=p;i<=n;i++)
for(int j=m;j>=a[i].w;j--)
{
f[j] = max(f[j], f[j - a[i].w] + a[i].v);
}
printf("%lld\n",ans + f[m]);
}
return 0;
}