首页 > 其他分享 >多重背包问题

多重背包问题

时间:2023-10-20 11:45:09浏览次数:38  
标签:多重 char 背包 int max 问题 物品 ldots

明天 2023 CSP 了,简单写写,以后在补吧。

题目描述

P1833 樱花

给你若干个物品,每个物品有体积 \(t_i\),价值 \(c_i\),每个物品可以拿 \(p_i\) 次。特别的,当 \(p_i=0\) 的时候,这个物品可以取无数次。

具体思路

solution 1:朴素背包

  • 对于 \(p_i=0\) 的物品,我们可以看成一个完全背包。

  • 对于 \(p_i \ne 0\) 的物品,我们可以在 01 背包的基础上多枚举一个 \(k\),表示当前第 \(i\) 个物品取多少个。

时间复杂度:\(O(nv \max \limits_{i \in [1,n]} \{ p_i \})\)

Code:

#include<bits/stdc++.h>
using namespace std;
const int N=1e4+5,M=1e3+5,D=10;
int t[N],c[N],p[N],f[M];
char st[D],ed[D];
int get(int l,int r,char *s){
	int res=0;
	for(int i=l;i<=r;i++){
		res=res*10+(s[i]-'0');
	}
	return res;
}
int main(){
	int minx,secx,miny,secy,n,v;
	scanf("%s%s%d",st+1,ed+1,&n);
	for(int i=1;i<=strlen(st+1);i++){
		if(st[i]==':'){
			minx=get(1,i-1,st);
			secx=get(i+1,strlen(st+1),st);
		}
	}
	for(int i=1;i<=strlen(ed+1);i++){
		if(ed[i]==':'){
			miny=get(1,i-1,ed);
			secy=get(i+1,strlen(ed+1),ed);
		}
	}
	v=(miny*60+secy)-(minx*60+secx);
	for(int i=1;i<=n;i++){
		scanf("%d%d%d",&t[i],&c[i],&p[i]);
	}
	for(int i=1;i<=n;i++){
		if(!p[i])
			for(int j=t[i];j<=v;j++)
				f[j]=max(f[j],f[j-t[i]]+c[i]);
		else
			for(int j=v;j>=t[i];j--)
				for(int k=1;k<=p[i];k++)
					if(j-k*t[i]>=0)
						f[j]=max(f[j],f[j-k*t[i]]+k*c[i]);
	}
	int ans=0;
	for(int i=0;i<=v;i++){
		ans=max(ans,f[i]);
	}
	printf("%d",ans);
	return 0;
}

solution 2:二进制拆分(优化)

我们发现,上面枚举次数 \(k\) 的行为实际上是将第 \(i\) 个物品拆成 \(p_i\) 个次数为 \(1\) 的物品,每个物品体积和价值分别是 \(t_i,c_i\)。

但这样有可能会超时(上面的代码由于数据水所以也过了)。

因此我们发明了二进制拆分。

众所周知,任何一个数都可以用二进制来表示,那么我们现在将第 \(i\) 个物品拆成 \(\log p_i\) 个次数分别为 \(1,2,4,\ldots\) 的物品,每个物品的体积分别是 \(t_i,2t_i,4t_i,\ldots\),价值分别为 \(c_i,2c_i,4c_i,\ldots\)。

那么对于完全背包,我们就不用管次数了,一直拆分直到 \(2^k t_i>v\)。

时间复杂度:\(O(nv \max \limits_{i \in [1,n]} \{ \log p_i \})\)

Code:

#include<bits/stdc++.h>
using namespace std;
const int N=1e4+5,M=1e6+5,D=10;
int t[N],c[N],p[N],f[M];
int a[M],w[M],cnt;
char st[D],ed[D];
int get(int l,int r,char *s){
	int res=0;
	for(int i=l;i<=r;i++){
		res=res*10+(s[i]-'0');
	}
	return res;
}
int main(){
	int minx,secx,miny,secy,n,v;
	scanf("%s%s%d",st+1,ed+1,&n);
	for(int i=1;i<=strlen(st+1);i++){
		if(st[i]==':'){
			minx=get(1,i-1,st);
			secx=get(i+1,strlen(st+1),st);
		}
	}
	for(int i=1;i<=strlen(ed+1);i++){
		if(ed[i]==':'){
			miny=get(1,i-1,ed);
			secy=get(i+1,strlen(ed+1),ed);
		}
	}
	v=(miny*60+secy)-(minx*60+secx);
	for(int i=1;i<=n;i++){
		scanf("%d%d%d",&t[i],&c[i],&p[i]);
		if(p[i]){
			int k=0;
			while(p[i]>=(1<<k)){
				cnt++;
				a[cnt]=t[i]*(1<<k);
				w[cnt]=c[i]*(1<<k);
				p[i]=p[i]-(1<<k);
				k++;
			}
			if(p[i]){
				cnt++;
				a[cnt]=t[i]*p[i];
				w[cnt]=c[i]*p[i];
			}
		}
		else{
			int k=0;
			while(t[i]*(1<<k)<=v){
				cnt++;
				a[cnt]=t[i]*(1<<k);
				w[cnt]=c[i]*(1<<k); 
				k++;
			}
		}
	}
	for(int i=1;i<=cnt;i++){
		for(int j=v;j>=a[i];j--){
			f[j]=max(f[j],f[j-a[i]]+w[i]);
		}
	}
	int ans=0;
	for(int i=0;i<=v;i++){
		ans=max(ans,f[i]);
	}
	printf("%d",ans);
	return 0;
}

标签:多重,char,背包,int,max,问题,物品,ldots
From: https://www.cnblogs.com/reclusive2007/p/17776711.html

相关文章

  • 项目开发中遇到的问题总结
    1、echarts图表问题数据库中存储结构为横向一条数据包含体重,身高,血糖血压,添加事件等数据而前端需要纵向以属性为y轴,事件为纵轴,分别产生多张表格。需要前端使用javascript进行遍历,使用到了map方法this.status=response.data.dataconsole.log(this.status)constxData=thi......
  • vscode 上无法 prettier 加载配置文件失败的问题
    1.prettier的配置文件有几种格式,先按照官方文档 配置好2.如果想按住Ctrl+Alt+L格式化代码,需要关闭vscode中的formatOnSave3.每次修改完设置需要重启vscode,这里重启的正确步骤:File->CloseFolder,再重新打开项目注意:不要直接关闭vscode窗口,这样重新打开vscod......
  • Redis代替session需要考虑的问题
    Redis代替session需要考虑的问题◆选择合适的数据结构◆选择合适的key◆选择合适的存储粒度......
  • OSS存储挂载权限问题
    https://help.aliyun.com/zh/ack/ack-managed-and-ack-dedicated/user-guide/faq-about-oss-volumes-1?spm=5176.smartservice_service_robot_chat_new.0.0.5a1b3f1b4TfffU#section-x2l-anl-0qz创建PV需要加上参数:otherOpts:'-oallow_other'设置挂载目录的权限为777......
  • Android 一例Base64错误问题
    在Android11下正常,8.1下不正常修改importimportorg.apache.commons.codec.binary.Base64;为importandroid.util.Base64;publicstaticStringencrypt(Stringdata){try{SecretKeysecretKey=newSecretKeySpec(SECRET_KEY.getBytes(),ENCRYPT......
  • JSON 返回数据命名不规范问题
    问题描述后端代码如下:@DatapublicclassUserDto{privateStringmUserName;privateStringmPassword;}@RestController@Slf4jpublicclassUserController{@PostMapping("/user")publicStringgetUserData(@RequestBodyUserDtouserDto){......
  • QT mocs_compilation.cpp 中出现多重定义问题
     在qt自动生成moc时,报自动生成的cpp中的方法重定义redefinitionof‘constQMetaObject*xxx::metaObject()const’等等查看mocs_compilation.cpp 发现其中有两行一样的cpp,这种情况大家可能会第一时间去排查是不是.h文件被包含了两次,但是发现.h文件都是#ifndef了的这种......
  • 记一次在服务器上运行node.js程序时无法通过nohup xxx & 方式挂起的问题
       由于业务需求每天要在服务器上整理一组数据,为了方便就用node.js来写了。但是运行的时候发现了一个问题明明使用了nohupmain.js&的方式后台运行了程序但是一旦我关闭了shell控制台这个后台运行的程序也会跟着终止掉,不知道是什么原因,于是采用forever.js的方式来运行......
  • 解决winform调用wpf窗体时原窗体缩小的问题
    在使用winform调用wpf窗体时,原来的winform窗体会缩小,同时分辨率会发生变化,用如下方法来解决这个问题。方法一、首先找到winform项目中的Properties ==>AssemblyInfo.cs,打开该文件,在末尾加入如下代码,之后重新运行即可。[assembly:System.Windows.Media.DisableDpiAwareness]/......
  • 由Django-Session配置引发的反序列化安全问题
    漏洞成因漏洞成因位于目标配置文件settings.py下关于这两个配置项SESSION_ENGINE:在Django中,SESSION_ENGINE 是一个设置项,用于指定用于存储和处理会话(session)数据的引擎。SESSION_ENGINE 设置项允许您选择不同的后端引擎来存储会话数据,例如:数据库后端 (django.contrib.sessions.b......