[贪心][完全背包]JZOJ 6309 完全背包

Description
 
Input
Output
 
Sample Input
Sample 1:
2 15
3 2
5 3

Sample 2:
3 70
71 100
69 1
1 2
 
Sample Output
Sample 1:
10

Sample 2:
140
 
 
Data Constraint

分析

这题终于用到了当年我学背包的时候想到过的贪心思想了

首先有用的物品不超过100个,如果a相同只要b最大的

然后有引理:给定n个整数,其中任意整数的和一定为n的倍数

然后我们将物品的性价比排序,如果性价比相同要体积小一点的

然后我们考虑背包的一大部分空间用性价比最高的物品填充,那么填充多少呢?

引理:其他非性价比最高的物品的个数<性价比最高的物品体积

因为当上面的符号变成≥时,一定有一部分体积的和是性价比最高体积的倍数,用它替换不会变劣

所以就要填充$\left \lfloor \frac{m}{a_{best}} \right \rfloor -100$个性价比最高物品

剩下做完全背包即可

 

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef long long ll;
const int N=1e5+10;
struct Item {
    ll a,b;
}t[20*N];
int n,n1;
ll f[N],ans,lans,m;

bool CMP(Item a,Item b) {return a.b*b.a>b.b*a.a||a.b*b.a==b.b*a.a&&a.a<b.a;}

bool CMP1(Item a,Item b) {return a.a<b.a||a.a==b.a&&a.b<b.b;}

int main() {
    freopen("backpack.in","r",stdin);
    freopen("backpack.out","w",stdout);
    scanf("%d%lld",&n,&m);
    for (int i=1;i<=n;i++) scanf("%lld%lld",&t[i].a,&t[i].b);
    sort(t+1,t+n+1,CMP1);n1=n;n=0;
    for (int i=1;i<=n1;i++) if (t[i].a!=t[i+1].a) t[++n]=t[i];
    sort(t+1,t+n+1,CMP);
    if (m/t[1].a>=100ll) ans=(m/t[1].a-100ll)*t[1].b,m-=((m/t[1].a)-100ll)*t[1].a;
    for (int i=0;i<=m;i++)
        for (int j=1;j<=n;j++)
            if (i+t[j].a<=m) f[i+t[j].a]=max(f[i+t[j].a],f[i]+t[j].b);
    for (int i=0;i<=m;i++) lans=max(lans,f[i]);
    printf("%lld\n",ans+lans);
}
View Code

 

转载于:https://www.cnblogs.com/mastervan/p/11375047.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值