Luogu P1858 多人背包
题意
题目描述
求01背包前k优解的价值和
输入输出格式
输入格式:
第一行三个数K、V、N
接下来每行两个数,表示体积和价值
输出格式:
前k优解的价值和
输入输出样例
输入样例#1:
2 10 5
3 12
7 20
2 4
5 6
1 1
输出样例#1:
57
说明
对于100%的数据,K≤50,V≤5000,N≤200
思路
让我先秒了这道水题。 --Mercury
多重背包。考场上考到的时候使用的是STL中的优先队列求解,即对于每一个V状态开一个优先队列,更新时逐个取出再插入,超过50个时后面的不用再插回去了。
这是一种显然的蚊子打高射炮高射炮打蚊子的做法,我们不妨这么想:
对于一般的01背包问题,我们有标准的状态转移方程f[i]=max(f[i],f[i−v[j]]+w[j])(i≥v[j])。也就是说,对于每个物品而言,状态f[i]只与f[i]和f[i−v[j]]有关,所以我们不妨设计f[i][j]表示f[i]的第j优解,更新时因为f[i][j]是有单调性的,所以拿单调指针从左往右扫一遍,扫出k个最优解,来更新就好了:
for(int i=V;i>=v[j];i--)//01背包倒序枚举
{
int cnt=0,cfr=0,cto=0;//cnt记录更新后的解,cto记录更新前的解,cfr记录f[i-v[j]]的解
while(cnt<k)//找到k个解
if(f[i][cto]>f[i-v[j]][cfr]+w[j]) tmp[cnt++]=f[i][cto++];//扫描
else tmp[cnt++]=f[i-v[j]][cfr++]+w[j];
for(int w=0;w<k;w++) f[i][w]=tmp[w];//更新
}
AC代码
#include<bits/stdc++.h>
using namespace std;
int k,v,n,ans,f[5005][55],tmp[55];
int read()
{
int re=0;char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) re=(re<<3)+(re<<1)+ch-'0',ch=getchar();
return re;
}
int main()
{
k=read(),v=read(),n=read();
memset(f,0xcf,sizeof f);
f[0][0]=0;
while(n--)
{
int x=read(),y=read();
for(int i=v;i>=x;i--)
{
int cnt=0,cfr=0,cto=0;
while(cnt<k)
if(f[i][cto]>f[i-x][cfr]+y) tmp[cnt++]=f[i][cto++];
else tmp[cnt++]=f[i-x][cfr++]+y;
for(int j=0;j<k;j++) f[i][j]=tmp[j];
}
}
for(int i=0;i<k;i++) ans+=f[v][i];
printf("%d",ans);
return 0;
}
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· dotnet 源代码生成器分析器入门
· ASP.NET Core 模型验证消息的本地化新姿势
· 对象命名为何需要避免'-er'和'-or'后缀
· SQL Server如何跟踪自动统计信息更新?
· AI与.NET技术实操系列:使用Catalyst进行自然语言处理
· 官方的 MCP C# SDK:csharp-sdk
· 一款 .NET 开源、功能强大的远程连接管理工具,支持 RDP、VNC、SSH 等多种主流协议!
· 提示词工程师自白:我如何用一个技巧解放自己的生产力
· 一文搞懂MCP协议与Function Call的区别
· 如何不购买域名在云服务器上搭建HTTPS服务