lintcode:背包问题
在n个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m,每个物品的大小为A[i]
样例
如果有4个物品[2, 3, 5, 7]
如果背包的大小为,可以选择[2, 3, 5]装入背包,最多可以装满的空间。
如果背包的大小为,可以选择[2, 3, 7]装入背包,最多可以装满的空间。
函数需要返回最多能装满的空间大小。
解题
动态规划
这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。
用子问题定义状态:即f[i][j]前i个物品放入大小为j的空间里能够占用的最大体积。
则其状态转移方程便是:
f[i][j]=max{f[i-1][j],f[i-1][j-A[i]]+A[i]}
不放第i个物品:f[i-1][j]
放第i个物品:那么问题就转化为“前i-1件物品放入剩下的容量为j-A[i]的背包中”,此时能获得的最大体积就是f[i-1][j-A[i]]再加上通过放入第i件物品获得的体积A[i]
注意上面的状态转移方程i的下标是从1开始的,下面程序是从0开始的,要适当调整
public class Solution {
/**
* @param m: An integer m denotes the size of a backpack
* @param A: Given n items with size A[i]
* @return: The maximum size
*/
public int backPack(int m, int[] A) {
// write your code here
int[][] P = new int[A.length+1][m+1];
for(int i = 1;i<= A.length; i++){
for(int j = m;j>=0;j--){
if(j>=A[i-1]){
P[i][j] = P[i-1][j-A[i-1]] + A[i-1];
}
P[i][j] = Math.max(P[i][j],P[i-1][j]);
}
}
return P[A.length][m];
}
}
或者对0的时候单独考虑
public class Solution {
/**
* @param m: An integer m denotes the size of a backpack
* @param A: Given n items with size A[i]
* @return: The maximum size
*/
public int backPack(int m, int[] A) {
// write your code here
int[][] P = new int[A.length][m+1];
for(int i = 0;i< A.length; i++){
for(int j = m;j>=0;j--){
if(i==0){ // 第0个物品可以放入空间为j的背包中,直接放入
if(j>=A[i])
P[i][j] = P[i][j-A[i]] + A[i];
}else{
if(j>=A[i]){
P[i][j] = P[i-1][j-A[i]] + A[i];
}
P[i][j] = Math.max(P[i][j],P[i-1][j]);
}
}
}
return P[A.length-1][m];
}
}
上面的时间空间复杂度都是O(MN)
状态转移方程式:
f[i][j] = Max(f[i-1][j],f[i-1][j-A[i]]+A[i])
f[i][j]表示对前i个物品,j的空间所能够取得的最大价值
实际上,我们需要求的是对所有的n个商品在m的空间中能够放入的最大价值
可以修改定义一个一维矩阵,长度就是m的空间的价值
f[j] = Max(f[j],f[j-A[i]]+A[i]) 这里就相当于对上面的矩阵进行了压缩
public class Solution {
/**
* @param m: An integer m denotes the size of a backpack
* @param A: Given n items with size A[i]
* @return: The maximum size
*/
public int backPack(int m, int[] A) {
// write your code here
int[] P = new int[m+1];
for(int i=0;i<A.length;i++){
for(int j=m;j>=0;j--){
if(j>=A[i])
P[j] = Math.max(P[j],P[j-A[i]] + A[i]);
}
}
return P[m];
}
}
参考:http://love-oriented.com/pack/P01.html
可以输出零钱的具体方案
package org.oj.dp; import java.util.ArrayList;
import java.util.Arrays; public class 换零钱问题 {
static ArrayList<ArrayList<String>> lists;
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] A = {1,2,5,10,20,50}; lists = new ArrayList<ArrayList<String>>(11);
ArrayList<String> l1 = new ArrayList<String>();
l1.add("");
lists.add(l1);
for(int i=0;i<11;i++){
lists.add(new ArrayList<String>(10));
}
changeMoney(A,10);
System.out.println(lists);
}
/**
* 根据上一个零钱方案,更新当前零钱方案
* @param A
* @param money
*/
private static void changeMoney(int[]A,int money){
int[] dp = new int[money+1];
dp[0] = 1;
for(int i=0;i<A.length;i++){
for(int j=A[i];j<=money;j++){
dp[j] +=dp[j-A[i]];
// 记录零钱方案
for(int k=0;k<lists.get(j-A[i]).size();k++){
lists.get(j).add(lists.get(j-A[i]).get(k)+" "+A[i]);
}
}
}
System.out.println(Arrays.toString(dp));
}
/**
* DFS实现
* @param m
* @param A
* @param start
* @param result
* @param str
*/
private static void DFS(int m,int[]A,int start,ArrayList<String>result,String str){
if(m == 0){
result.add(str);
return;
}
if(A[start]> m){
return;
}
for(int i = start;i<A.length;i++){
DFS(m - A[i],A,i,result,str+ " "+A[i]);
}
} }
lintcode:背包问题的更多相关文章
- lintcode:背包问题II
背包问题II 给出n个物品的体积A[i]和其价值V[i],将他们装入一个大小为m的背包,最多能装入的总价值有多大? 注意事项 A[i], V[i], n, m均为整数.你不能将物品进行切分.你所挑选的 ...
- 背包问题2 (lintcode)
这里: for(int j = 1;j <= m;j++) result[0][j] = 0x80000000; 不能从0开始,result[0][0]是可以取到的,是0.其他情况取不到才用最小 ...
- 92.背包问题(lintcode)
注意j-A[i-1]必须大于等于0,只大于0会报错 class Solution { public: /** * @param m: An integer m denotes the size of ...
- leetcode & lintcode for bug-free
刷题备忘录,for bug-free leetcode 396. Rotate Function 题意: Given an array of integers A and let n to be it ...
- leetcode & lintcode 题解
刷题备忘录,for bug-free 招行面试题--求无序数组最长连续序列的长度,这里连续指的是值连续--间隔为1,并不是数值的位置连续 问题: 给出一个未排序的整数数组,找出最长的连续元素序列的长度 ...
- lintcode 题目记录3
Expression Expand Word Break II Partition Equal Subset Sum Expression Expand 字符串展开问题,按照[]前的数字展开字符 ...
- lintcode算法周竞赛
------------------------------------------------------------第七周:Follow up question 1,寻找峰值 寻找峰值 描述 笔记 ...
- [LintCode]——目录
Yet Another Source Code for LintCode Current Status : 232AC / 289ALL in Language C++, Up to date (20 ...
- (lintcode全部题目解答之)九章算法之算法班题目全解(附容易犯的错误)
--------------------------------------------------------------- 本文使用方法:所有题目,只需要把标题输入lintcode就能找到.主要是 ...
随机推荐
- iOS UI高级之网络编程(HTTP协议)
HTTP协议的概念 HTTP协议,Hyper Text Transfer Protocol (超文本传输协议)是用于从万维网服务器传送超文本到本地浏览器的传输协议,HTTP是一个应用层协议,由请求和响 ...
- MVC 中如何将带有标签的字符串转换为HTML 标签 显示出来?
出现问题的现象:
- 微软职位内部推荐-SDEII for Windows Phone Apps
微软近期Open的职位: Job title: Software Design Engineer II Location: China, Beijing Division: Operations Sy ...
- c读取文本文档
想数一下文本文档一共有多少行,写了个小程序 1.用fopen()以只读方式打开文件 2.用fgetc()获取文件流中的字符内容 3.如果字符内容为'\n'换行符,count++ 最后输出count的值 ...
- 单元测试篇----cppUnit的安装与使用
在刚学习单元测试章节的时候,尝试着使用dev—c++来编译cppunit,但一直没成功,也尝试问过同学,一直没有很好的方法,因此浪费了不少时间.今天又耐心的尝式一下,意外成功了.以下是详细的安装步骤: ...
- SQL中的5种聚集函数
作为一个刚毕业进入这行的菜鸟,婶婶的觉的那种大神.大牛到底是怎样炼成的啊,我这小菜鸟感觉这TMD要学的东西这多啊,然后就给自己定了许多许多要学习的东西,可是有人又不停地给你灌输:东西不在多而要精通!我 ...
- android应用程序的安装方式与原理
android应用程序的安装方式与原理 四种安装方式: 1.系统应用安装――开机时完成,没有安装界面 2.网络下载应用安装――通过market应用完成,没有安装界面 3.ADB工具安装――没有安装界面 ...
- ASP.NET本质论阅读----线程与异步
线程 概要:操作系统通过线程对程序的执行进行管理 线程的数据结构:1.线程的核心对象(包含线程的当前寄存器状态),调用线程时-寄存器状态被加载到CPU中. 2.线程环境块TEB:一块用户模式下的内存 ...
- android 自动化压力测试-monkey 1 实践
Monkey是Android中的一个命令行工具,可以运行在模拟器里或实际设备中.它向系统发送伪随机的用户事件流(如按键输入.触摸屏输入.手势输入等),实现对正在开发的应用程序进行压力测试.Monkey ...
- 使用log4javascript记录日志
1.定义log4js服务类,用于初始化log4javascript相关参数 log4jsService.js //启用javascript 日志功能 var logger = log4javascri ...