Processing math: 100%

极大容量的完全背包问题

题目大意:

就是题目名称的意思,有n种物品,一个容量为m的背包,每种物品的体积为ai,价值为bi,有n<=106,m<=1018,ai,bi<=100。求最大价值。

解题方法:

因为m很大,所以我们考虑将较大的体积为S的背包分为较小的两个背包,其中一个体积为x,则另一个S-x。

这时讨论abs(x-(S-x))的范围,可以推出其<=maxv(物品的最大体积)。因为单独对两个背包操作,两边会有余留下来的部分,将其中一个余留下来的部分补到另一个去可能会得到更忧解。但如果移动的部分大于maxv了则放在两个背包中的任意一个都可以得到最优解。所以我们成功将枚举区间缩小到了Smaxv2<=x<=S+maxv2

然后我们类似分治的套路将图画出来:

发现MaxMin<2×maxv并且最底层(即Min>0的最后一层)的Min<=maxv,Max<=3×maxv,所以我们可以预处理出3×maxv大小的背包就可以得到最底层的解,然后我们可以记录每层最小值L[i]即最左边的点的权值,设g[i][j]表示在第i层时比L[i]容量大j的背包的最优解,枚举x逐层向上转移即可,转移方程:g[i][vL[i]]=max(g[i+1][xL[i+1]]+g[i+1][vxL[i+1]])

因为一开始给了106种物品,然而因为最多有100×100种物品,所以可以用set去重。

代码:

复制代码
 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define del(a,b) memset(a,b,sizeof(a))
 4 using namespace std;
 5 const int MAXN=1e5+10;
 6 ll n,m,tot;
 7 set<int> ap[110];
 8 ll f[MAXN],g[55][MAXN],L[55],a[MAXN],b[MAXN];
 9 void Max(ll &a,ll b){a=(a>b? a:b);}
10 template <class T>void read(T &x)
11 {
12     bool f=0;char ch=getchar();x=0;
13     for(;ch<'0' || ch>'9';ch=getchar())if(ch=='-') f=1;
14     for(;ch>='0' && ch<='9';ch=getchar())x=x*10+ch-'0';
15     if(f) x=-x;
16 }
17 int main()
18 {
19     read(n);read(m);
20     ll maxv=0;
21     for(int i=1;i<=n;i++)
22     {
23         ll x,y;read(x);read(y);
24         if(ap[x].find(y)!=ap[x].end()) continue;
25         a[++tot]=x;b[tot]=y;ap[x].insert(y);
26         Max(maxv,a[tot]);
27     }
28     ll s=m,cnt=0;
29     while(s>0)
30     {
31         L[++cnt]=s;
32         s=(s-maxv)>>1;
33     }
34     for(int i=1;i<=tot;i++)
35     for(int v=a[i];v<=maxv*3;v++)
36         Max(f[v],f[v-a[i]]+b[i]);
37     for(int i=cnt;i>=1;i--)
38     for(ll v=L[i];v<=L[i]+maxv*2;v++)
39     {
40         if(v<=maxv*3) g[i][v-L[i]]=f[v];
41         else
42         {
43             for(ll x=(v-maxv)>>1;x<=v>>1;x++)
44             Max(g[i][v-L[i]],g[i+1][x-L[i+1]]+g[i+1][v-x-L[i+1]]);
45         }
46     }
47     printf("%lld",g[1][0]);
48     return 0;
49 }
View Code
复制代码

 

posted @   Oracle_LinJH  阅读(2042)  评论(0编辑  收藏  举报
编辑推荐:
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ASP.NET Core 模型验证消息的本地化新姿势
阅读排行:
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· .NET 原生驾驭 AI 新基建实战系列(一):向量数据库的应用与畅想
· Ai满嘴顺口溜,想考研?浪费我几个小时
· Browser-use 详细介绍&使用文档
· 软件产品开发中常见的10个问题及处理方法
点击右上角即可分享
微信分享提示