当前位置: 首页 > news >正文

0/1背包经典例题 入门动态规划

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

  笔者参加美团在线笔试的时候,遇到了一道动态规划的相关题目,很遗憾当时的笔者非常稚嫩,对算法简直一窍不通,于是抱着求学的态度,打算入门动态规划的时候,发现了这个经典的动态规划(Dynamic Programming,DP)入门题--0/1背包问题,看完大神们的解答思路,简直顶礼膜拜,于是打算自己手动实现下,致敬大佬们。特此,摘记。

  所谓的0/1表示的就是装入背包的物品只有两种状态(装入与不装入)。   OK,废话不多说,上题:

题目:

条件:
* 一个背包,最大容量12Kg
* 5个物品,分别的重量为1 , 3 , 2 , 6 , 2(单位都是Kg),分别的价值为2 , 5 , 3 , 10 , 4(这个单位任意)
问题:
* 求背包最多能装下多少价值的物品?

  OK,谈下解题思路:

  1. 确认子问题和状态   01背包问题需要求解的就是,为了体积V的背包中物体总价值最大化,N件物品中第i件应该放入背包中吗?(其中每个物品最多只能放一件)   为此,我们定义一个二维数组,其中每个元素代表一个状态,即前i个物体中若干个放入体积为V背包中最大价值。数组为:f[N][V],其中fij表示前i件中若干个物品放入体积为j的背包中的最大价值。
  2. 初始状态   初始状态为f[0][0−V]和f[0−N][0]都为0,前者表示前0个物品(也就是空物品)无论装入多大的包中总价值都为0,后者表示体积为0的背包啥价值的物品都装不进去。
  3. 转移函数
if (背包体积j小于物品i的体积)
    f[i][j] = f[i-1][j] //背包装不下第i个物体,目前只能靠前i-1个物体装包
else
    f[i][j] = max(f[i-1][j], f[i-1][j-Vi] + Wi)

  最后一句的意思就是根据“为了体积V的背包中物体总价值最大化,N件物品中第i件应该放入背包中吗?”转化而来的。Vi表示第i件物体的体积,Wi表示第i件物品的价值。这样f[i-1][j]代表的就是不将这件物品放入背包,而f[i-1][j-Vi] + Wi则是代表将第i件放入背包之后的总价值,比较两者的价值,得出最大的价值存入现在的背包之中。

OK,上笔者自己撸的代码:

package package_0_1;

/**
 * 0/1 背包问题
 * @author xiao
 *
 */
public class Package01 { 
	// 背包的最大重量
	public static int package_weight_max = 12;
	// 一共有几种物品
	public static int Total_Item = 5;
	// 每种物品的价值
	public static int[] values= {0 , 2 , 5 , 3 , 10 , 4};
	// 每种物品的重量
	public static int[] Items_Weight = {0 , 1 , 3 , 2 , 6 , 2};
	/* 一个二维数组,用来表示从前i个物品里
	 * 选出最合适的装进载重量为j背包中,使
	 * 得背包里的价值最大。i∈Items j∈{0-package_weight_max}
	 * dp[i][j] 单位是 (价值)
	*/
	public static int dp[][] = new int[Total_Item+1][package_weight_max+1];
	
	/**
	 * 初始化dp二维数组
	 */
	public static void initialize_dp() {
		for(int[] i : dp) {
			for(int j :i) {
				j=0;
			}
		}
	}
	
	/**
	 * DP 计算递推矩阵(求出每个局部最优解,将其保存进二维数组,方便递推)
	 */
	public static int DPMethod() {
		initialize_dp();
		
		// 构造二维数组
		for(int i = 1;i<=Total_Item;i++) {
			for(int j = 1;j<=package_weight_max;j++) {
				/* 如果背包容量小于物品的重量,则不放入此物品,
				 * 将放入上一物品的最大价值作为这次的最大价值
				 */
				if(j<Items_Weight[i]) {
					dp[i][j] = dp[i-1][j];
				}
				/* 如果背包容量足够放下这件物品,那么就
				 * 比较不放入物品时的最大价值与放入此物
				 * 品时的最大价值谁大,将大的作为这次的最大价值
				 */
				else {
					// GetMax(不放入物品的价值,此物品的价值+剩余空间的最大价值)
					dp[i][j] = GetMax(dp[i-1][j],(dp[i-1][j-Items_Weight[i]]+values[i]));
				}
				System.out.print(dp[i][j]+" ");
			}
			System.out.println("");
		}
		// 至此求得解
		return dp[Total_Item][package_weight_max];
	}
	
	/**
	 * 求最大值
	 * @param i
	 * @param j
	 * @return
	 */
	private static int GetMax(int i, int j) {
		// TODO Auto-generated method stub
		if(i>j) {
			return i;
		}else {
			return j;
		}
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println("计算矩阵如下: ");
		int result = DPMethod();
		System.out.println(String.format("12kg背包最多能装进价值为 %d 的物品", result));
	}

}

OK,先记录到这!

转载于:https://my.oschina.net/u/3744313/blog/1649501

相关文章:

  • HDU 2242 考研路茫茫——空调教室(边双连通)
  • Inno 安装前检测.net framework 4.0
  • MySQL5.7 添加用户、删除用户与授权
  • Puppeteer:浏览器控制器
  • Centos 如何双击执行可执行程序
  • 大幕已拉开,人工智能离我们还有多远?
  • SpringBoot2系列教程(二)maven项目包 (特别完整!)
  • 如何用 SpringBoot 优雅的写代码
  • postgres 错误
  • 如何在C#项目中使用NHibernate
  • JAVA多线程机制解析-volatilesynchronized
  • 基于hi-nginx的web开发(python篇)——cookie和会话管理
  • hostPath Volume - 每天5分钟玩转 Docker 容器技术(148)
  • 使用vigil 监控微服务系统包含可视化界面
  • Centos查看端口占用情况和开启端口命令
  • 网络传输文件的问题
  • 自己简单写的 事件订阅机制
  • css属性的继承、初识值、计算值、当前值、应用值
  • nginx 负载服务器优化
  • passportjs 源码分析
  • spring boot下thymeleaf全局静态变量配置
  • sublime配置文件
  • ⭐ Unity 开发bug —— 打包后shader失效或者bug (我这里用Shader做两张图片的合并发现了问题)
  • vue脚手架vue-cli
  • webgl (原生)基础入门指南【一】
  • yii2权限控制rbac之rule详细讲解
  • 阿里云容器服务区块链解决方案全新升级 支持Hyperledger Fabric v1.1
  • 短视频宝贝=慢?阿里巴巴工程师这样秒开短视频
  • 关于 Cirru Editor 存储格式
  • 基于遗传算法的优化问题求解
  • 罗辑思维在全链路压测方面的实践和工作笔记
  • MPAndroidChart 教程:Y轴 YAxis
  • !$boo在php中什么意思,php前戏
  • #android不同版本废弃api,新api。
  • (八)光盘的挂载与解挂、挂载CentOS镜像、rpm安装软件详细学习笔记
  • (第二周)效能测试
  • (附源码)springboot优课在线教学系统 毕业设计 081251
  • (黑马出品_高级篇_01)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
  • (七)Knockout 创建自定义绑定
  • (三) prometheus + grafana + alertmanager 配置Redis监控
  • (十五)使用Nexus创建Maven私服
  • (四)docker:为mysql和java jar运行环境创建同一网络,容器互联
  • (一)Java算法:二分查找
  • (已解决)报错:Could not load the Qt platform plugin “xcb“
  • (转)AS3正则:元子符,元序列,标志,数量表达符
  • (转载)VS2010/MFC编程入门之三十四(菜单:VS2010菜单资源详解)
  • .bat批处理(一):@echo off
  • .NET 3.0 Framework已经被添加到WindowUpdate
  • .net 程序发生了一个不可捕获的异常
  • .net 流——流的类型体系简单介绍
  • .NET/C# 将一个命令行参数字符串转换为命令行参数数组 args
  • .NET设计模式(11):组合模式(Composite Pattern)
  • .NET正则基础之——正则委托
  • @configuration注解_2w字长文给你讲透了配置类为什么要添加 @Configuration注解
  • [ C++ ] STL---string类的模拟实现