版权声明:版权声明:本文为博主原创文章,未经博主允许不得转载,欢迎添加友链。 https://blog.csdn.net/zzk_233/article/details/83010978
这道题求得是所有的贡献值v和所有的重量w的最大比值。。但是正常的背包开不下,性质符不符合我也不确定。
即求,但是我们可以考虑每个点选与不选的状态,设这种状态为g[i],只有0和1两种状态,所以叫01分数规划。
这时状态就转为,对于这个答案ans可以二分答案。
每次只要保证,这样每次枚举到lim就好,不用枚举总重量。
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
int n,lim;
ll w[260],v[260],f[1000006];
ll check(ll x)
{
for(int i=1;i<=lim;i++)
{
f[i]=-0x3f3f3f3f;
}
f[0]=0;
for(int i=1;i<=n;i++)
{
for(int j=lim;j>=0;j--)
{
if(f[j]!=-0x3f3f3f3f)
{
f[min((ll)lim,(ll)j+w[i])]=max(f[min((ll)lim,(ll)j+w[i])],f[j]+v[i]-w[i]*x);
}
}
}
return f[lim]>=0;
}
ll findf()
{
ll l=0,r=0x3f3f3f3f,mid;
while(l<=r)
{
mid=(l+r)/2;
if(check(mid))l=mid+1;
else r=mid-1;
}
return r;
}
int main()
{
scanf("%d%d",&n,&lim);
for(int i=1;i<=n;i++)
{
scanf("%lld%lld",&w[i],&v[i]);
v[i]*=1000;
}
printf("%lld",findf());
return 0;
}