ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

一本通1268:【例9.12】完全背包问题(完全背包问题详解)

2020-09-25 18:01:54  阅读:430  来源: 互联网

标签:1268 01 int 重量 9.12 ch include 背包


原题传送门

一道完全背包问题模板题,和01背包问题一样,还是拥有两种思路

\(Solution\ 1\)

依然是一个朴实无华的二维数组

状态的表示:\(f[i][j]\)表示前\(i\)个总重量不超过\(j\)的最大价值

状态的转移:\(f[i][j]=max(f[i-1][j],f[i][j-w[i]]+c[i])\ (w[i]<=j)\)
注:\(w[i]\)表示第\(i\)个物品的重量,\(c[i]\)表示第\(i\)个物品的价值,\(j\)表示当前的最大重量

最优解:\(f[n][m]\)
注:\(n\)指物体数量,\(m\)指最大重量

\(Code\)

#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
inline void read(int &x){
	int f=1;
	char ch=getchar();
	x=0;
	while(ch<'0'||ch>'9'){
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	x*=f;
}
int m,n;
int w[31],c[31];
int f[201][201];
int main(){
	read(m);read(n);
	for(int i=1;i<=n;i++){
		read(w[i]);
		read(c[i]);
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(j<w[i]) f[i][j]=f[i-1][j];
			else f[i][j]=max(f[i-1][j],f[i][j-w[i]]+c[i]); 
		}
	}
	printf("max=%d",f[n][m]);      //"max="是题目中的输出格式要求
	return 0;
}

\(Solution\ 2\)

依然可以用一维数组来进行空间优化

状态的表示:\(f[i]\)表示不超过\(i\)重量的最大价值

状态的转移:\(f[j]=max(f[j],f[j-w[i]]+c[i])\)
注:\(w[i]\)表示第i个物品的重量,\(c[i]\)表示第i个物品的价值,\(j\)表示当前的最大重量

最优解:\(f[m]\)
注:\(m\)指最大重量

\(Code\)

#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
inline void read(int &x){
	int f=1;
	char ch=getchar();
	x=0;
	while(ch<'0'||ch>'9'){
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	x*=f;
}
int m,n;
int w[31],c[31];
int f[201];
int main(){
	read(m);read(n);
	for(int i=1;i<=n;i++){
		read(w[i]);
		read(c[i]);
	}
	for(int i=1;i<=n;i++){
		for(int j=w[i];j<=m;j++){
			f[j]=max(f[j],f[j-w[i]]+c[i]);
		}
	}
	printf("max=%d",f[m]);      //"max="是题目中的输出格式要求
	return 0;
}

这里和\(01\)背包唯一不同的是,内层循环变成了这个:

for(int j=1;j<=m;j++)

和这个

for(int j=w[i];j<=m;j++)

在\(01\)背包里,\(j\)是从最大重量\(m\)进行倒序遍历到\(w[i]\)的。而这里,是从\(w[i]\)正序遍历到最大重量\(m\)
这便是\(01\)背包和完全背包在一维数组实现上的唯一不同之处
原因还是来源于本质区别:

  • \(01\)背包是只有选和不选两个子问题
  • 完全背包是有选和不选两个子问题,但是选里边还有选几个的若干子问题

所以说,考虑“再选一个第\(i\)种物品”的方案时,有可能已经选过一个第\(i\)件物品,当前行的\(f[j]\)需要用到前面的的结果。

即由于一个物品可以被选择多次,更新\(f[i][j]\)时,\(f[i][j-w[i]]\)可能因为放入物品i而发生变化。所以说需要正序循环。

标签:1268,01,int,重量,9.12,ch,include,背包
来源: https://www.cnblogs.com/-pwl/p/13731583.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有