珠宝 (01背包,四边形不等式)

news/发布时间2024/5/19 21:01:43

\(01\) 背包的 trick。

Link.

做法 \(1\)

暴力背包。超时。

做法 \(2\)

一个显然的性质就是,按 \(c_i\) 归类,先用价值大的。

如果无法更新背包,直接退出循环即可。

亲测能获得 85pts 的好成绩。

时间复杂度同暴力背包。(理论)

做法 \(3\)

如果你认真打了表,会发现如果从大往小放,那么最后一个更新的点是在递增的。

这一个很好理解,更新点只会右移。

加上这个小优化,虽然理论复杂度和暴力没区别,但是就是能草过去。

点击查看代码
#include<bits/stdc++.h>
#define N 50005
#define M 305
#define ll long long
#define reg register
using namespace std;
int n,m;
ll f[N];
vector <int>E[M];
inline int read()
{int s=0;char c=getchar();while(c<'0'||c>'9') c=getchar();while(c>='0'&&c<='9'){s=(s<<3)+(s<<1)+c-'0';c=getchar();}return s;
}
int main()
{
//	freopen("a1.in","r",stdin);n=read(),m=read();for(reg int i=1;i<=n;i++){int c,v;c=read(),v=read();E[c].push_back(v);}for(reg int i=1;i<=M-5;i++){if(E[i].empty()) continue;sort(E[i].begin(),E[i].end());int used=1,pos=i;for(reg int k=E[i].size()-1;k>=0;k--){int now=E[i][k];used=0;for(reg int j=m;j>=pos;j--)if(f[j]<f[j-i]+now) f[j]=f[j-i]+now,used=j;pos=used;if(!used) break;}}for(int i=1;i<=m;i++) printf("%lld ",f[i]);return 0;
}

做法 \(4\)

所以在同一纬度内有决策单调性。

我们定义 \(f_{i,j}\) 表示第 \(i\) 类物品花 \(j\) 元的最大价值。

所以转移方程是 \(f_{i,j}=\min f_{i-1,j-kc}+w(k)\)

\(k\) 分类转移即可。

时间复杂度 \(O(Cm\log m)\)

#include<bits/stdc++.h>
#define N 50005
#define M 305
#define K 1000005
#define ll long long
#define reg register
using namespace std;
int n,m;
ll f[N],g[N];
vector <ll>E[M];
inline int read()
{int s=0;char c=getchar();while(c<'0'||c>'9') c=getchar();while(c>='0'&&c<='9'){s=(s<<3)+(s<<1)+c-'0';c=getchar();}return s;
}
ll sum[K];
void solve(int l,int r,int ql,int qr,int k,int cur)
{if(l>r||ql>qr) return;int mid=(l+r)/2*k+cur;ll maxx=-1;int pos=1145141919;for(int i=ql;i<=min(mid,qr);i+=k)if(g[i]+sum[(mid-i)/k]>maxx) maxx=g[i]+sum[(mid-i)/k],pos=i;f[mid]=maxx;mid=(l+r)/2;solve(l,mid-1,ql,pos,k,cur);solve(mid+1,r,pos,qr,k,cur);
}
int main()
{n=read(),m=read();for(reg int i=1;i<=n;i++){int c,v;c=read(),v=read();E[c].push_back(v);}for(reg int i=1;i<=M-5;i++){if(E[i].empty()) continue;sort(E[i].begin(),E[i].end());int len=E[i].size();memset(sum,0,sizeof sum);for(reg int k=1;k<=min(len,m);k++)sum[k]=sum[k-1]+1ll*E[i][len-k];for(int i=len+1;i<=m;i++) sum[i]=sum[i-1];memcpy(g,f,sizeof g);for(int k=0;k<i;k++){int R=(m/i)*i+k;if(R>m) R-=i;solve(0,(R-k)/i,k,R,i,k);}}for(int i=1;i<=m;i++) printf("%lld ",f[i]);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ulsteruni.cn/article/86743155.html

如若内容造成侵权/违法违规/事实不符,请联系编程大学网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

minio 修改默认密码

运行后data目录会生成一个隐层文件夹【.minio.sys】 打开.minio.sys/config/config.jsonaccess_key,secret_key即为账号密码(默认账号密码均为minioadmin) 默认密码修改以后可以在系统内部添加其他账号对外使用留待后查,同时方便他人 联系我:renhanlinbsl@163.com

在鼠标右键菜单中新增新建Markdown文件选项(VSCode)

引言 正常情况下,我们新建md文件有两种方式:一是通过Markdown编辑器新建,二是新建txt文件再修改后缀。 但是在Windows系统中,我们可以通过修改注册表来新增右键菜单选项。这里我们可以通过修改注册表来新增新建Markdown文件选项,这样可以减少新建文件的繁琐操作。 下面就来…

搭建https的es+kibana(7.9.1)

背景:elasticsearch7需要开启https才可以创建报警,因此就需要搭建https的elasticsearch 参考官方网站:https://www.elastic.co/guide/en/cloud-on-k8s/current/k8s-deploy-elasticsearch.html第一步,创建crdkubectl create -f https://download.elastic.co/downloads/eck/2…

MATLAB中simulink中scope同时显示两个输入信号

在使用scope时,需要两个输入信号的设置方法 1.点开scope图标2 点击设置按钮, 然后弹出configuration properties:scope配置图,在Main选项下,在Number of input ports:1这里面更改数字,需要几个输入信号就更改几,此时这里更改为23 设置layout 选择自己喜欢的窗口显示排列…

使用joinjs绘制流程图(六)-自定义节点成html元素

场景 有的时候流程图中的节点是多样化的 效果代码 <template><div class="app"><el-button type="primary" size="small" @click="updateRectContent">修改Rect元素内容</el-button><hr /><div ref=…

JAVA下唯一一款搞定OLTP+OLAP的强类型查询这就是最好用的ORM相见恨晚

JAVA下唯一一款搞定OLTP+OLAP的强类型查询这就是最好用的ORM相见恨晚 介绍 首先非常感谢 FreeSQL 提供的部分源码,让我借鉴了不少功能点,整体设计并没有参考FreeSQL(因为java压根没有expression所以没办法参考)只是在数据库方言上FreeSQL提供的SQL让我少走了很多弯路,所以才让e…